Android ABI'lar

Farklı Android cihazlar farklı CPU'lar kullanır, bu da farklı CPU'ları destekler talimat setlerinden yararlanın. Her CPU ve talimat grubu kombinasyonunun kendine ait Uygulama İkili Arabirimi (ABI). ABI aşağıdaki bilgileri içerir:

  • Kullanılabilen CPU talimat grubu (ve uzantıları).
  • Çalışma zamanında depolanan bellek ve yüklemelerin sabitliği. Android her zaman küçük Endian.
  • Uygulamalar ile sistem arasında veri aktarımına yönelik kurallar ve ve sistemin, yığın ve yapılandırma kullandığı işlevi çağırdığında kaydedilir.
  • Programlar ve paylaşılan kitaplıklar gibi yürütülebilir ikili programların biçimi, içerik türlerini açıkladık. Android her zaman ELF'yi kullanır. Daha fazla bkz. ELF System V Uygulama İkili Arabirimi.
  • C++ adlarının nasıl karıştırıldığı. Daha fazla bilgi için bkz. Genel/Itanyum C++ ABI.

Bu sayfa, NDK'nın desteklediği ABI'leri sıralar ve bilgi sağlar her bir ABI'nın işleyiş şekli hakkında.

ABI, platform tarafından desteklenen yerel API'ye de başvurabilir. Örneğin, 32 bit sistemleri etkileyen bu ABI sorunlarının listesini görmek için 32 bit ABI hataları.

Desteklenen ABI'ler

Tablo 1. ABI'ler ve desteklenen talimat grupları.

ABI Desteklenen Talimat Setleri Notlar
armeabi-v7a
  • Ermeabi
  • Beğeni-2
  • Neon
  • ARMv5/v6 cihazlarla uyumlu değildir.
    arm64-v8a
  • Arch64
  • Yalnızca Armv8.0.
    x86
  • x86 (IA-32)
  • MİKS
  • SSE/3/2
  • SSSE3
  • MOVBE veya SSE4 desteklenmemektedir.
    x86_64
  • x86-64
  • MİKS
  • SSE/3/2
  • SSSE3
  • SSE4.1, 4.2
  • POPCNT
  • Tam x86-64-v1, ancak yalnızca kısmi x86-64-v2 (CMPXCHG16B veya LAHF-SAHF yok).

    Not: NDK tarafından desteklenen ARMv5 geçmişte (armeabi) ve 32 bit ve 64 bit MIPS'ye sahiptir, ancak bu ABI'ler için sağlanan destek NDK r17.

    ermeabi-v7a

    Bu ABI, 32 bit ARM CPU'lar içindir. Thumb-2 ve Neon dahildir.

    ABI'nın Android'e özgü olmayan bölümleri hakkında bilgi için bkz. ARM Mimarisi için Uygulama İkili Arabirimi (ABI)

    NDK'nın derleme sistemleri Android.mk içindeki LOCAL_ARM_MODE CMake'i yapılandırırken ndk-build veya ANDROID_ARM_MODE adresine gidin.

    Neon geçmişi hakkında daha fazla bilgi için Neon Desteği bölümüne bakın.

    Bu ABI, geçmişe dönük nedenlerle, tüm float nedenlerinden dolayı -mfloat-abi=softfp tam sayı kayıtlarında iletilecek değerler ve tüm double değerleri iletilecek tamsayı kayıt çiftleri kullanarak fonksiyon çağrıları yaparken dikkate alınmaz. Adının aksine, yalnızca kayan nokta çağrı kuralını etkiler: derleyici yine de aritmetik için donanım kayan nokta talimatlarını kullanın.

    Bu ABI, 64 bit bir long double kullanır (IEEE ikili programı64 ve double ile aynıdır).

    kol64-v8a

    Bu ABI, 64 bit ARM CPU'lar içindir.

    Bkz. Arm's Mimariyi Öğrenme sayfasına göz atın. Kol bazı taşıma tavsiyeleri de sunar. 64 bit Android Geliştirme.

    Neon yerleşik özelliklerini kullanabilirsiniz? C ve C++ koduna ekleyebilirsiniz. İlgili içeriği oluşturmak için kullanılan Armv8-A için Neon Programcı Kılavuzu dahili Neon programlama ve Neon programlama hakkında daha fazla bilgi sağlar.

    Android'de platforma özel x18 kaydı, ShadowCallStack ve kodunuzdan dokunulmamalıdır. Clang'in mevcut sürümleri varsayılan olarak Android'de -ffixed-x18 seçeneğini kullanabilirsiniz. Dolayısıyla, el yazısıyla (veya çok eski bir derleyici) bu konuda endişelenmeniz gerekmez.

    Bu ABI, 128 bit bir long double (IEEE ikili 128) kullanır.

    x86

    Bu ABI, yaygın olarak "x86" olarak bilinen talimat setini destekleyen CPU'lar ve "i386" veya "IA-32".

    Android'in ABI'si, temel talimat setini ve MMX SSE, SSE2, SSE3 ve SSSE3 uzantıları hakkında daha fazla bilgi edinin.

    ABI, başka isteğe bağlı IA-32 talimat seti içermez MOVBE veya SSE4'ün herhangi bir varyantı gibi uzantılar bulunmalıdır. Bu uzantıları kullanmaya devam etmek için çalışma zamanı özellik incelemesini ve desteklemeyen cihazlar için yedekler sağlar.

    NDK araç zincirinde, işlev çağrısından önce 16 baytlık yığın hizalaması varsayılır. Varsayılan araçlar ve bu kuralı zorunlu kılar. Derleme kodu yazıyorsanız yığında diğer derleyicilerin de bu kurala uyduğundan emin olun.

    Daha fazla bilgi için aşağıdaki belgelere bakın:

    Bu ABI, 64 bit bir long double kullanır (IEEE ikili programı64 double ile aynıdır ve daha fazlası değil genel 80 bit yalnızca Intel long double).

    x86_64

    Bu ABI, yaygın olarak adı verilen talimat grubunu destekleyen CPU'lar içindir. "x86-64".

    Android'in ABI'si, temel talimat setini ve MMX SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 ve POPCNT talimatı.

    ABI, başka isteğe bağlı x86-64 talimat seti içermez MOVBE, SHA veya AVX'in herhangi bir varyantı gibi uzantılar. Bu uzantıları kullanmaya devam etmek için çalışma zamanı özelliğini ve desteklemeyen cihazlar için yedekler sağlar.

    Daha fazla bilgi için aşağıdaki belgelere bakın:

    Bu ABI, 128 bit bir long double (IEEE ikili 128) kullanır.

    Belirli bir ABI için kod oluşturun

    Gradle

    Gradle derlemeleri (ister Android Studio aracılığıyla ister komut satırından olsun) varsayılan olarak, desteği sonlandırılmamış tüm ABI'lerdir. Ayarladığınız ABI grubunu kısıtlamak için: için abiFilters kullanın. Örneğin, 64 bit ABI'ler varsa build.gradle cihazınızda aşağıdaki yapılandırmayı ayarlayın:

    android {
        defaultConfig {
            ndk {
                abiFilters 'arm64-v8a', 'x86_64'
            }
        }
    }
    

    ndk-kurum

    ndk-build derlemeleri için varsayılan olarak kullanımdan kaldırılmamış tüm ABI'ler kullanılır. Bir Application.mk dosyanızda APP_ABI ayarlayarak belirli ABI'leri oluşturun. İlgili içeriği oluşturmak için kullanılan aşağıdaki snippet'te APP_ABI kullanımıyla ilgili birkaç örnek gösterilmektedir:

    APP_ABI := arm64-v8a  # Target only arm64-v8a
    APP_ABI := all  # Target all ABIs, including those that are deprecated.
    APP_ABI := armeabi-v7a x86_64  # Target only armeabi-v7a and x86_64.
    

    APP_ABI için belirtebileceğiniz değerler hakkında daha fazla bilgi edinmek üzere Application.mk.

    CMake

    CMake ile, aynı anda tek bir ABI için derleme yaparsınız ve ABI'nızı belirtmeniz gerekir açık bir şekilde belirtmelisiniz. Bu işlemi, ANDROID_ABI değişkeniyle yapabilirsiniz. belirtilmiş olmalıdır (CMakeLists.txt dosyanızda ayarlanamaz). Örneğin, örnek:

    $ cmake -DANDROID_ABI=arm64-v8a ...
    $ cmake -DANDROID_ABI=armeabi-v7a ...
    $ cmake -DANDROID_ABI=x86 ...
    $ cmake -DANDROID_ABI=x86_64 ...
    

    NDK ile derlemek için CMake'e iletilmesi gereken diğer flag'ler için bkz. CMake kılavuzu'na bakabilirsiniz.

    Derleme sisteminin varsayılan davranışı, her ABI için ikili programları eklemektir şişman APK olarak da bilinen tek bir APK içinde kullanılabilir. Yağlı APK, önemli ölçüde daha büyük tek bir ABI için ikili programları içeren bir ayardan daha iyidir; eşitlik kazanıyor daha büyük bir APK pahasına daha geniş kapsamlı uyumluluk sağlamaya çalışır. Kesinlikle iOS ve Android cihazınızda App Bundle veya APK Bölmelerinden maksimum cihaz değerini korurken APK'larınızın boyutunu küçültün uyumluluk.

    Yükleme sırasında, paket yöneticisi yalnızca en uygun hedef cihazın makine koduna uygulanır. Ayrıntılar için yerel koda karşılık gelecek şekilde gönderin.

    Android platformunda ABI yönetimi

    Bu bölümde, Android platformunun yerel reklamları nasıl yönettiği hakkında ayrıntılar verilmiştir için de geçerlidir.

    Uygulama paketlerinde yerel kod

    Hem Play Store hem de Paket Yöneticisi, NDK tarafından oluşturulan içerikleri bulmayı bekler APK'nın içindeki dosya yollarında bulunan kitaplıklar:

    /lib/<abi>/lib<name>.so
    

    Burada <abi>, Desteklenen ABI'ler altında listelenen ABI adlarından biridir. <name> ise LOCAL_MODULE için tanımladığınız kitaplığın adıdır değişkenini Android.mk dosyasında görebilirsiniz. Başlangıç APK dosyaları yalnızca zip dosyalarıdır. Bunları açmak ve paylaşılan yerel dosyanın kitaplıklar da buradadır.

    Sistem, beklediği yerde paylaşılan yerel kitaplıkları bulamazsa gerekir. Böyle bir durumda, uygulamanın kendisi kitaplıkları kopyalayın ve ardından dlopen() gerçekleştir.

    Yağ APK'sında her kitaplık, adı karşılık gelen ABI ile eşleşen bir dizin altında bulunur. Örneğin, yağlı bir APK şunları içerebilir:

    /lib/armeabi/libfoo.so
    /lib/armeabi-v7a/libfoo.so
    /lib/arm64-v8a/libfoo.so
    /lib/x86/libfoo.so
    /lib/x86_64/libfoo.so
    

    Not: 4.0.3 veya önceki sürümleri çalıştıran ARMv7 tabanlı Android cihazlar armeabi-v7a yerine armeabi dizininden yerel kitaplıklar yükle dizini de oluşturur. Çünkü /lib/armeabi/, APK'da /lib/armeabi-v7a/. Bu sorun 4.0.4 sürümünde düzeltilmiştir.

    Android platformu ABI desteği

    Derlemeye özgü sistem, Android sistemi çalışma zamanında hangi ABI'leri desteklediğini bilir özellikleri şunları gösterir:

    • Cihaz için, kullanılan makine koduna karşılık gelen birincil ABI sistem görüntüsünün kendisini.
    • İsteğe bağlı olarak, sistem görüntüsünün kullandığı diğer ABI'lere karşılık gelen ikincil ABI'ler desteği de sunar.

    Bu mekanizma, sistemin Google Cloud Platform'dan en iyi makine kodunu dikkat edin.

    En iyi performans için doğrudan birincil ABI için derleme yapmanız gerekir. Örneğin, tipik ARMv5TE tabanlı cihazlar yalnızca birincil ABI'yı tanımlar: armeabi. Buna karşılık, ARMv7 tabanlı normal bir cihaz, birincil ABI'yı armeabi-v7a ve ikincil ABI olarak tanımlar Her biri için oluşturulan uygulama yerel ikili programlarını çalıştırabileceğinden, bir armeabi olarak ayarlanmalıdır.

    64 bit cihazlar da 32 bit varyantlarını destekler. arm64-v8a cihazlarını kullanma cihaz, armeabi ve armeabi-v7a kodunu da çalıştırabilir. Not, 64 bit cihazlarda ise uygulamanızın çok daha iyi performans göstereceğini armeabi-v7a çalıştıran cihaza güvenmek yerine arm64-v8a'yı hedeflediğinden sürümünü kullandığınızdan emin olun.

    x86 tabanlı birçok cihaz, armeabi-v7a ve armeabi NDK ikililerini de çalıştırabilir. Örneğin, birincil ABI x86, ikincisi ise armeabi-v7a olur.

    Belirli bir ABI için apk'yi zorunlu yükleyebilirsiniz. Bu, test için yararlıdır. Aşağıdaki komutu kullanın:

    adb install --abi abi-identifier path_to_apk
    
    .

    Yükleme sırasında yerel kodu otomatik olarak ayıklama

    Paket yöneticisi hizmeti, bir uygulama yüklerken APK'yı tarar ve uygulama yüklenirken, biçimin paylaşılan kitaplıklarını:

    lib/<primary-abi>/lib<name>.so
    

    Hiçbir şey bulunamazsa ve ikincil bir ABI tanımladıysanız hizmet, şu formu kullanın:

    lib/<secondary-abi>/lib<name>.so
    

    Aradığı kitaplıkları bulduğunda paket yöneticisi, bunları, uygulamanın yerel kitaplık dizinindeki /lib/lib<name>.so konumuna taşıma (<nativeLibraryDir>/). Aşağıdaki snippet'ler nativeLibraryDir öğesini alır:

    Kotlin

    import android.content.pm.PackageInfo
    import android.content.pm.ApplicationInfo
    import android.content.pm.PackageManager
    ...
    val ainfo = this.applicationContext.packageManager.getApplicationInfo(
            "com.domain.app",
            PackageManager.GET_SHARED_LIBRARY_FILES
    )
    Log.v(TAG, "native library dir ${ainfo.nativeLibraryDir}")
    

    Java

    import android.content.pm.PackageInfo;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageManager;
    ...
    ApplicationInfo ainfo = this.getApplicationContext().getPackageManager().getApplicationInfo
    (
        "com.domain.app",
        PackageManager.GET_SHARED_LIBRARY_FILES
    );
    Log.v( TAG, "native library dir " + ainfo.nativeLibraryDir );
    

    Paylaşılan nesne dosyası yoksa uygulama derlenir ve yüklenir ancak belirler.

    ARMv9: C/C++ için PAC ve BTI'yı etkinleştirme

    PAC/BTI'nin etkinleştirilmesi bazı saldırı vektörlerine karşı koruma sağlar. PAC, iade adreslerini bir işlevin dosyasında kriptografik olarak imzalayarak korur. ve iade adresinde hâlâ doğru e-posta adresinin bölüm. BTI, Her şube hedefinin özel bir talimat olduğunu, başka hiçbir şey yapmayan kabul etmesini sağlayan taraftır.

    Android, mevcut işlemcilerde herhangi bir işlem yapmayan PAC/BTI talimatlarını yeni talimatları desteklemez. PAC/BTI yalnızca ARMv9 cihazlarda bulunur ancak aynı kodu ARMv8 cihazlarda da çalıştırabilirsiniz: kitaplığınızın birden fazla varyantını bulabilirsiniz. ARMv9 cihazlarda bile PAC/BTI yalnızca geçerlidir 64 bit koda dönüştürün.

    PAC/BTI'nin etkinleştirilmesi, kod boyutunda küçük bir artışa (genellikle %1) neden olur.

    Arm'ın Mimari hakkında bilgi edinin: karmaşık yazılımlar (PDF) PAC/BTI hedefine ait saldırı vektörlerinin ve bu hedefin nasıl çalıştığını anlıyoruz.

    Derleme değişiklikleri

    ndk-kurum

    Android.mk dosyanızın her modülünde LOCAL_BRANCH_PROTECTION := standard değerini ayarlayın.

    CMake

    target_compile_options($TARGET PRIVATE -mbranch-protection=standard) hesabını kullan sizin CMakeLists.txt dosyanızdaki her hedef için.

    Diğer derleme sistemleri

    Kodunuzu -mbranch-protection=standard kullanarak derleyin. Yalnızca bu işaret kullanılabilir arm64-v8a ABI için derleme yaparken Aşağıdaki durumlarda bu işareti kullanmanız gerekmez: bağlanıyor.

    Sorun giderme

    PAC/BTI için derleyici desteğiyle ilgili herhangi bir sorundan haberdar değiliz, ancak:

    • Bağlama işlemi sırasında BTI ve BTI olmayan kodları birlikte kullanmamaya dikkat edin. BTI korumasının etkin olmadığı bir kitaplıkla sonuçlanır. Tekliflerinizi otomatikleştirmek ve optimize etmek için llvm-readelf adresini ziyaret ederek sonuç kitaplığınızda BTI notu olup olmadığını kontrol edebilirsiniz.
    $ llvm-readelf --notes LIBRARY.so
    [...]
    Displaying notes found in: .note.gnu.property
      Owner                Data size    Description
      GNU                  0x00000010   NT_GNU_PROPERTY_TYPE_0 (property note)
        Properties:    aarch64 feature: BTI, PAC
    [...]
    $
    
    • OpenSSL'nin eski (1.1.1i öncesi) sürümlerinde elle yazılmış derleyicide hata bulunuyor bu da PAC hatalarına neden olur. Geçerli OpenSSL'ye yükseltin.

    • Bazı uygulamaların DRM sistemlerinin eski sürümleri, PAC/BTI kodunu ihlal eden kod oluşturuyor. gereksinimlerini karşılayın. Uygulama DRM kullanıyorsanız ve PAC/BTI'yı etkinleştirirken sorun yaşıyorsanız sabit sürüm için DRM tedarikçi firmanızla görüşün.