ABI kararlılığı

Tedarikçi modülleri, sistem bölümünde bulunan Tedarikçi Yerel Geliştirme Kiti (VNDK) paylaşılan kitaplıklarına bağlı olabileceğinden, Yalnızca Çerçeve Güncellemeleri için Uygulama İkili Arayüzü (ABI) kararlılığı ön koşuldur. Yeni oluşturulan VNDK paylaşılan kitaplıkları, bir Android sürümünde daha önce yayınlanan VNDK paylaşılan kitaplıklarıyla ABI uyumlu olmalıdır. Böylece tedarikçi modülleri, bu kitaplıklarla yeniden derleme ve çalışma zamanı hatası olmadan çalışabilir. Android sürümleri arasında VNDK kitaplıkları değiştirilebilir ve ABI garantisi verilmez.

Android 9, ABI uyumluluğunu sağlamak için aşağıdaki bölümlerde açıklandığı gibi bir üstbilgi ABI denetleyicisi içerir.

VNDK ve ABI uyumluluğu hakkında

VNDK, satıcı modüllerinin bağlanabileceği ve yalnızca çerçeve güncellemelerini etkinleştiren kısıtlayıcı bir kitaplıklar kümesidir. ABI uyumluluğu, paylaşılan bir kitaplığın yeni sürümünün, kendisine dinamik olarak bağlanmış bir modülle beklendiği gibi çalışabilmesini (ör. kitaplığın eski bir sürümü gibi çalışabilmesini) ifade eder.

Dışa aktarılan semboller hakkında

Dışa aktarılan sembol (küresel sembol olarak da bilinir), aşağıdakilerin tümünü karşılayan bir sembolü ifade eder:

  • Paylaşılan bir kitaplığın public üstbilgileri tarafından dışa aktarılır.
  • Paylaşılan kitaplığa karşılık gelen .so dosyasının .dynsym tablosunda görünür.
  • WEAK (ZAYIF) veya GLOBAL (GENEL) bağlama içeriyorsa
  • Görünürlük DEFAULT veya PROTECTED olmalıdır.
  • Bölüm dizini UNDEFINED değil.
  • Tür, FUNC veya OBJECT olmalıdır.

Paylaşılan bir kitaplığın public headers'ı, paylaşılan kitaplığa karşılık gelen modülün Android.bp tanımlarındaki export_include_dirs, export_header_lib_headers, export_static_lib_headers, export_shared_lib_headers ve export_generated_headers özellikleri aracılığıyla diğer kitaplıklar/ikili dosyalar tarafından kullanılabilen üstbilgiler olarak tanımlanır.

Ulaşılabilir türler hakkında

Ulaşılabilir tür, dışa aktarılan bir sembol aracılığıyla doğrudan veya dolaylı olarak ulaşılabilen VE herkese açık başlıklar aracılığıyla dışa aktarılan herhangi bir C/C++ yerleşik ya da kullanıcı tanımlı türdür. Örneğin, libfoo.so, .dynsym tablosunda bulunan dışa aktarılmış bir sembol olan Foo işlevine sahiptir. libfoo.so kitaplığı şunları içerir:

foo_exported.h foo.private.h
typedef struct foo_private foo_private_t;

typedef struct foo {
  int m1;
  int *m2;
  foo_private_t *mPfoo;
} foo_t;

typedef struct bar {
  foo_t mfoo;
} bar_t;

bool Foo(int id, bar_t *bar_ptr);
typedef struct foo_private {
  int m1;
  float mbar;
} foo_private_t;
Android.bp
cc_library {
  name : libfoo,
  vendor_available: true,
  vndk {
    enabled : true,
  }
  srcs : ["src/*.cpp"],
  export_include_dirs : [
    "exported"
  ],
}
.dynsym tablosu
Num Value Size Type Bind Vis Ndx Name
1 0 0 FUNC GLOB DEF UND dlerror@libc
2 1ce0 20 FUNC GLOB DEF 12 Foo

Foo'ya baktığımızda doğrudan/dolaylı olarak erişilebilen türler şunlardır:

Tür Açıklama
bool Foo dönüş türü.
int İlk Foo parametresinin türü.
bar_t * İkinci Foo parametresinin türü. bar_t * aracılığıyla, bar_t, foo_exported.h üzerinden dışa aktarılır.

bar_t, foo_exported.h üzerinden dışa aktarılan foo_t türünde bir mfoo üyesi içerir. Bu durum, daha fazla türün dışa aktarılmasına neden olur:
  • int :, m1 türüdür.
  • int * :, m2 türüdür.
  • foo_private_t * : , mPfoo türüdür.

Ancak foo_private_t, foo_exported.h üzerinden dışa aktarılmadığı için ulaşılamıyor. (foo_private_t * opak olduğundan foo_private_t üzerinde yapılan değişikliklere izin verilir.)

Temel sınıf belirleyicileri ve şablon parametreleri aracılığıyla erişilebilen türler için de benzer bir açıklama yapılabilir.

ABI uygunluğunu sağlama

İlgili Android.bp dosyalarında vendor_available: true ve vndk.enabled: true ile işaretlenen kitaplıklar için ABI uyumluluğu sağlanmalıdır. Örneğin:

cc_library {
    name: "libvndk_example",
    vendor_available: true,
    vndk: {
        enabled: true,
    }
}

Dışa aktarılan bir işlev tarafından doğrudan veya dolaylı olarak erişilebilen veri türleri için, kitaplıkta yapılan aşağıdaki değişiklikler ABI'yi bozan değişiklikler olarak sınıflandırılır:

Veri türü Açıklama
Yapılar ve Sınıflar
  • Sınıf türünün veya yapı türünün boyutunu değiştirin.
  • Temel sınıflar
    • Temel sınıflar ekleyin veya kaldırın.
    • Sanal olarak devralınan temel sınıfları ekleme veya kaldırma
    • Temel sınıfların sırasını değiştirme
  • Üye işlevleri
    • Üyelere özel işlevleri kaldırın*.
    • Üye işlevlerine bağımsız değişken ekleme veya bu işlevlerden bağımsız değişken kaldırma
    • Üye işlevlerinin bağımsız değişken türlerini veya dönüş türlerini değiştirme*.
    • Sanal tablo düzenini değiştirme
  • Veri üyeleri
    • Statik veri üyelerini kaldırın.
    • Statik olmayan veri üyeleri ekleme veya kaldırma
    • Veri üyelerinin türlerini değiştirme.
    • Ofsetleri statik olmayan veri üyeleriyle değiştirin**.
    • Veri üyelerinin const, volatile ve/veya restricted niteleyicilerini değiştirin***.
    • Veri üyelerinin erişim belirleyicilerini düşürme***.
  • Şablon bağımsız değişkenlerini değiştirin.
Sendikalar
  • Veri üyesi ekleme veya kaldırma
  • Birleşim türünün boyutunu değiştirin.
  • Veri üyelerinin türlerini değiştirme.
Numaralandırmalar
  • Temel türü değiştirme
  • Numaralandırıcıların adlarını değiştirme
  • Numaralandırıcıların değerlerini değiştirin.
Global Symbols
  • Herkese açık başlıklar tarafından dışa aktarılan sembolleri kaldırın.
  • FUNC türündeki global semboller için
    • Bağımsız değişken ekleyin veya kaldırın.
    • Bağımsız değişken türlerini değiştirin.
    • Dönüş türünü değiştirme
    • Erişim belirleyiciyi düşürün***.
  • OBJECT türündeki genel semboller için
    • İlgili C/C++ türünü değiştirin.
    • Erişim belirleyiciyi düşürün***.

* Herkese açık satır içi işlevler, özel üye işlevlerine başvurabileceğinden hem herkese açık hem de özel üye işlevleri değiştirilmemeli veya kaldırılmamalıdır. Özel üye işlevlerine yapılan sembol referansları, arayan ikili dosyalarında tutulabilir. Paylaşılan kitaplıklardaki özel üye işlevlerinin değiştirilmesi veya kaldırılması, geriye dönük olarak uyumsuz ikili dosyalarla sonuçlanabilir.

** Satır içi işlevler, işlev gövdelerinde bu veri üyelerine başvurabileceğinden, herkese açık veya özel veri üyelerine yönelik ofsetler değiştirilmemelidir. Veri üyesi ofsetlerinin değiştirilmesi, eski sürümlerle uyumsuz ikili dosyalarla sonuçlanabilir.

*** Bunlar türün bellek düzenini değiştirmese de kitaplıkların beklendiği gibi çalışmamasına neden olabilecek anlamsal farklılıklar vardır.

ABI uyumluluk araçlarını kullanma

Bir VNDK kitaplığı oluşturulduğunda kitaplığın ABI'si, oluşturulan VNDK sürümünün karşılık gelen ABI referansıyla karşılaştırılır. Referans ABI dökümleri şu konumda bulunur:

${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/<PLATFORM_VNDK_VERSION>/<BINDER_BITNESS>/<ARCH>/source-based

Örneğin, API düzeyi 27'de x86 için libfoo oluşturulurken libfoo'nın çıkarılan ABI'si şu adresteki referansıyla karşılaştırılır:

${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/27/64/x86/source-based/libfoo.so.lsdump

ABI bozulması hatası

ABI bozulmalarında, derleme günlüğünde uyarı türü ve abi-diff raporunun yoluyla ilgili uyarılar gösterilir. Örneğin, libbinder'nın ABI'sinde uyumsuz bir değişiklik varsa derleme sistemi, aşağıdakine benzer bir mesajla hata verir:

*****************************************************
error: VNDK library: libbinder.so's ABI has INCOMPATIBLE CHANGES
Please check compatibility report at:
out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm64_armv8-a_cortex-a73_vendor_shared/libbinder.so.abidiff
******************************************************
---- Please update abi references by running
platform/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder ----

VNDK kitaplığı ABI kontrolleri oluşturma

Bir VNDK kitaplığı oluşturulduğunda:

  1. header-abi-dumper, VNDK kitaplığını oluşturmak için derlenen kaynak dosyaları (kitaplığın kendi kaynak dosyaları ve statik geçişli bağımlılıklar aracılığıyla devralınan kaynak dosyalar) işleyerek her kaynağa karşılık gelen .sdump dosyaları oluşturur.
    sdump oluşturma
    1. şekil. .sdump dosyalarını oluşturma
  2. header-abi-linker daha sonra, paylaşılan kitaplığa karşılık gelen tüm ABI bilgilerini kaydeden bir .lsdump dosyası oluşturmak için .sdump dosyalarını (kendisine sağlanan bir sürüm komut dosyasını veya paylaşılan kitaplığa karşılık gelen .so dosyasını kullanarak) işler.
    lsdump oluşturma
    Şekil 2. .lsdump dosyasını oluşturma
  3. header-abi-diff, iki kitaplığın ABI'lerindeki farklılıkları özetleyen bir fark raporu oluşturmak için .lsdump dosyasını bir referans .lsdump dosyasıyla karşılaştırır.
    abi diff creation
    3.şekil Fark raporu oluşturma

header-abi-dumper

header-abi-dumper aracı, bir C/C++ kaynak dosyasını ayrıştırır ve bu kaynak dosyasından çıkarılan ABI'yi bir ara dosyaya boşaltır. Derleme sistemi, derlenen tüm kaynak dosyalar üzerinde header-abi-dumper çalıştırırken geçişli bağımlılıklardaki kaynak dosyaları içeren bir kitaplık da oluşturur.

Girişler
  • C/C++ kaynak dosyası
  • Dışa aktarılan include dizinleri
  • Derleyici işaretleri
Çıkış Kaynak dosyanın ABI'sini açıklayan bir dosya (örneğin, foo.sdump , foo.cpp'nin ABI'sini temsil eder).

Şu anda .sdump dosyaları, gelecekteki sürümlerde kararlılığının garanti edilmediği JSON biçimindedir. Bu nedenle, .sdump dosya biçimlendirmesi, derleme sistemi uygulama ayrıntısı olarak kabul edilmelidir.

Örneğin, libfoo.so için aşağıdaki kaynak dosya foo.cpp'sı vardır:

#include <stdio.h>
#include <foo_exported.h>

bool Foo(int id, bar_t *bar_ptr) {
    if (id > 0 && bar_ptr->mfoo.m1 > 0) {
        return true;
    }
    return false;
}

Kaynak dosya tarafından sunulan ABI'yi temsil eden bir ara .sdump dosyası oluşturmak için header-abi-dumper aracını kullanabilirsiniz.

$ header-abi-dumper foo.cpp -I exported -o foo.sdump -- -I exported -x c++

Bu komut, header-abi-dumper'ya --'dan sonra gelen derleyici işaretleriyle foo.cpp'ı ayrıştırmasını ve exported dizinindeki herkese açık üstbilgiler tarafından dışa aktarılan ABI bilgilerini yayınlamasını söyler. Aşağıdaki foo.sdump, header-abi-dumper tarafından oluşturuldu:

{
 "array_types" : [],
 "builtin_types" :
 [
  {
   "alignment" : 4,
   "is_integral" : true,
   "linker_set_key" : "_ZTIi",
   "name" : "int",
   "referenced_type" : "_ZTIi",
   "self_type" : "_ZTIi",
   "size" : 4
  }
 ],
 "elf_functions" : [],
 "elf_objects" : [],
 "enum_types" : [],
 "function_types" : [],
 "functions" :
 [
  {
   "function_name" : "FooBad",
   "linker_set_key" : "_Z6FooBadiP3foo",
   "parameters" :
   [
    {
     "referenced_type" : "_ZTIi"
    },
    {
     "referenced_type" : "_ZTIP3foo"
    }
   ],
   "return_type" : "_ZTI3bar",
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "global_vars" : [],
 "lvalue_reference_types" : [],
 "pointer_types" :
 [
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP11foo_private",
   "name" : "foo_private *",
   "referenced_type" : "_ZTI11foo_private",
   "self_type" : "_ZTIP11foo_private",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP3foo",
   "name" : "foo *",
   "referenced_type" : "_ZTI3foo",
   "self_type" : "_ZTIP3foo",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIPi",
   "name" : "int *",
   "referenced_type" : "_ZTIi",
   "self_type" : "_ZTIPi",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "qualified_types" : [],
 "record_types" :
 [
  {
   "alignment" : 8,
   "fields" :
   [
    {
     "field_name" : "mfoo",
     "referenced_type" : "_ZTI3foo"
    }
   ],
   "linker_set_key" : "_ZTI3bar",
   "name" : "bar",
   "referenced_type" : "_ZTI3bar",
   "self_type" : "_ZTI3bar",
   "size" : 24,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "fields" :
   [
    {
     "field_name" : "m1",
     "referenced_type" : "_ZTIi"
    },
    {
     "field_name" : "m2",
     "field_offset" : 64,
     "referenced_type" : "_ZTIPi"
    },
    {
     "field_name" : "mPfoo",
     "field_offset" : 128,
     "referenced_type" : "_ZTIP11foo_private"
    }
   ],
   "linker_set_key" : "_ZTI3foo",
   "name" : "foo",
   "referenced_type" : "_ZTI3foo",
   "self_type" : "_ZTI3foo",
   "size" : 24,
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "rvalue_reference_types" : []
}

foo.sdump, kaynak dosya foo.cpp tarafından dışa aktarılan ABI bilgilerini ve herkese açık üstbilgileri (ör.

  • record_types. Herkese açık başlıklarda tanımlanan yapılar, birleşimler veya sınıflara bakın. Her kayıt türü; alanları, boyutu, erişim belirleyicisi, tanımlandığı başlık dosyası ve diğer özellikleriyle ilgili bilgiler içerir.
  • pointer_types. Genel başlıklardaki dışa aktarılan kayıtlar/işlevler tarafından doğrudan/dolaylı olarak referans verilen işaretçi türlerine ve işaretçinin işaret ettiği türe (type_info içindeki referenced_type alanı aracılığıyla) bakın. Nitelikli türler, yerleşik C/C++ türleri, dizi türleri, lvalue ve rvalue referans türleri için benzer bilgiler .sdump dosyasına kaydedilir. Bu tür bilgiler, yinelemeli farklılaştırmaya olanak tanır.
  • functions. Genel başlıklar tarafından dışa aktarılan işlevleri temsil edin. Ayrıca, işlevin bozulmuş adı, dönüş türü, parametre türleri, erişim belirleyici ve diğer özellikler hakkında bilgi içerirler.

header-abi-linker

header-abi-linker aracı, header-abi-dumper tarafından oluşturulan ara dosyaları giriş olarak alır ve bu dosyaları bağlar:

Girişler
  • header-abi-dumper tarafından oluşturulan ara dosyalar
  • Sürüm komut dosyası/harita dosyası (isteğe bağlı)
  • .so paylaşılan kitaplığın dosyası
  • Dışa aktarılan include dizinleri
Çıkış Paylaşılan bir kitaplığın ABI'sini açıklayan bir dosya (örneğin, libfoo.so.lsdump , libfoo'nin ABI'sini temsil eder).

Araç, kendisine verilen tüm ara dosyalardaki tür grafiklerini birleştirir ve çeviri birimleri arasındaki tek tanımlı (tam nitelikli adı aynı olan farklı çeviri birimlerindeki kullanıcı tanımlı türler, anlamsal olarak farklı olabilir) farklılıkları dikkate alır. Araç daha sonra, dışa aktarılan sembollerin listesini oluşturmak için bir sürüm komut dosyasını veya paylaşılan kitaplığın .dynsym tablosunu (.so dosyası) ayrıştırır.

Örneğin, libfoo, foo.cpp ve bar.cpp öğelerinden oluşur. header-abi-linker, libfoo'nin bağlantılı ABI dökümünü oluşturmak için aşağıdaki şekilde çağrılabilir:

header-abi-linker -I exported foo.sdump bar.sdump \
                  -o libfoo.so.lsdump \
                  -so libfoo.so \
                  -arch arm64 -api current

libfoo.so.lsdump içindeki örnek komut çıkışı:

{
 "array_types" : [],
 "builtin_types" :
 [
  {
   "alignment" : 1,
   "is_integral" : true,
   "is_unsigned" : true,
   "linker_set_key" : "_ZTIb",
   "name" : "bool",
   "referenced_type" : "_ZTIb",
   "self_type" : "_ZTIb",
   "size" : 1
  },
  {
   "alignment" : 4,
   "is_integral" : true,
   "linker_set_key" : "_ZTIi",
   "name" : "int",
   "referenced_type" : "_ZTIi",
   "self_type" : "_ZTIi",
   "size" : 4
  }
 ],
 "elf_functions" :
 [
  {
   "name" : "_Z3FooiP3bar"
  },
  {
   "name" : "_Z6FooBadiP3foo"
  }
 ],
 "elf_objects" : [],
 "enum_types" : [],
 "function_types" : [],
 "functions" :
 [
  {
   "function_name" : "Foo",
   "linker_set_key" : "_Z3FooiP3bar",
   "parameters" :
   [
    {
     "referenced_type" : "_ZTIi"
    },
    {
     "referenced_type" : "_ZTIP3bar"
    }
   ],
   "return_type" : "_ZTIb",
   "source_file" : "exported/foo_exported.h"
  },
  {
   "function_name" : "FooBad",
   "linker_set_key" : "_Z6FooBadiP3foo",
   "parameters" :
   [
    {
     "referenced_type" : "_ZTIi"
    },
    {
     "referenced_type" : "_ZTIP3foo"
    }
   ],
   "return_type" : "_ZTI3bar",
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "global_vars" : [],
 "lvalue_reference_types" : [],
 "pointer_types" :
 [
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP11foo_private",
   "name" : "foo_private *",
   "referenced_type" : "_ZTI11foo_private",
   "self_type" : "_ZTIP11foo_private",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP3bar",
   "name" : "bar *",
   "referenced_type" : "_ZTI3bar",
   "self_type" : "_ZTIP3bar",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP3foo",
   "name" : "foo *",
   "referenced_type" : "_ZTI3foo",
   "self_type" : "_ZTIP3foo",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIPi",
   "name" : "int *",
   "referenced_type" : "_ZTIi",
   "self_type" : "_ZTIPi",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "qualified_types" : [],
 "record_types" :
 [
  {
   "alignment" : 8,
   "fields" :
   [
    {
     "field_name" : "mfoo",
     "referenced_type" : "_ZTI3foo"
    }
   ],
   "linker_set_key" : "_ZTI3bar",
   "name" : "bar",
   "referenced_type" : "_ZTI3bar",
   "self_type" : "_ZTI3bar",
   "size" : 24,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "fields" :
   [
    {
     "field_name" : "m1",
     "referenced_type" : "_ZTIi"
    },
    {
     "field_name" : "m2",
     "field_offset" : 64,
     "referenced_type" : "_ZTIPi"
    },
    {
     "field_name" : "mPfoo",
     "field_offset" : 128,
     "referenced_type" : "_ZTIP11foo_private"
    }
   ],
   "linker_set_key" : "_ZTI3foo",
   "name" : "foo",
   "referenced_type" : "_ZTI3foo",
   "self_type" : "_ZTI3foo",
   "size" : 24,
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "rvalue_reference_types" : []
}

header-abi-linker aracı:

  • Kendisine sağlanan .sdump dosyalarını (foo.sdump ve bar.sdump) bağlar ve dizinde bulunan üstbilgilerde bulunmayan ABI bilgilerini filtreler: exported.
  • libfoo.so öğesini ayrıştırır ve kitaplığın .dynsym tablosu aracılığıyla dışa aktardığı sembollerle ilgili bilgileri toplar.
  • _Z3FooiP3bar ve _Z6FooBadiP3foo ekler.

libfoo.so.lsdump, libfoo.so'nin oluşturulan son ABI dökümüdür.

header-abi-diff

header-abi-diff aracı, iki kitaplığın ABI'sini temsil eden iki .lsdump dosyasını karşılaştırır ve iki ABI arasındaki farkları belirten bir diff raporu oluşturur.

Girişler
  • Eski bir paylaşılan kitaplığın ABI'sini temsil eden .lsdump dosyası.
  • Yeni bir paylaşılan kitaplığın ABI'sini temsil eden .lsdump dosyası.
Çıkış Karşılaştırılan iki paylaşılan kitaplık tarafından sunulan ABI'lerdeki farklılıkları belirten bir diff raporu.

ABI farklılık dosyası, protobuf metin biçimindedir. Biçim, gelecekteki sürümlerde değişebilir.

Örneğin, libfoo için iki sürümünüz var: libfoo_old.so ve libfoo_new.so. libfoo_new.so içinde, bar_t içinde, mfoo türünü foo_t olarak değiştiriyorsunuz.foo_t * bar_t, erişilebilir bir tür olduğundan bu, header-abi-diff tarafından ABI'yi bozan bir değişiklik olarak işaretlenmelidir.

header-abi-diff uygulamasını çalıştırmak için:

header-abi-diff -old libfoo_old.so.lsdump \
                -new libfoo_new.so.lsdump \
                -arch arm64 \
                -o libfoo.so.abidiff \
                -lib libfoo

libfoo.so.abidiff içindeki örnek komut çıkışı:

lib_name: "libfoo"
arch: "arm64"
record_type_diffs {
  name: "bar"
  type_stack: "Foo-> bar *->bar "
  type_info_diff {
    old_type_info {
      size: 24
      alignment: 8
    }
    new_type_info {
      size: 8
      alignment: 8
    }
  }
  fields_diff {
    old_field {
      referenced_type: "foo"
      field_offset: 0
      field_name: "mfoo"
      access: public_access
    }
    new_field {
      referenced_type: "foo *"
      field_offset: 0
      field_name: "mfoo"
      access: public_access
    }
  }
}

libfoo.so.abidiff, libfoo içindeki tüm ABI uyumluluğunu bozan değişikliklerin raporunu içerir. record_type_diffs mesajı, bir kaydın değiştiğini belirtir ve uyumsuz değişiklikleri listeler. Bu değişiklikler şunlardır:

  • Kaydın boyutu 24 bayttan 8 bayta değişiyor.
  • mfoo alanının türü foo olarak değiştirildi. foo * (Tüm typedef'ler kaldırıldı).

type_stack alanı, header-abi-diff öğesinin değişen türe (bar) nasıl ulaştığını gösterir. Bu alan, Foo öğesinin, bar * öğesini parametre olarak alan, dışa aktarılmış ve değiştirilmiş bar öğesini işaret eden bir işlev olarak yorumlanabilir.

ABI ve API'yi zorunlu kılma

VNDK paylaşılan kitaplıklarının ABI ve API'sini zorunlu kılmak için ABI referansları ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/'ya kaydedilmelidir. Bu referansları oluşturmak için aşağıdaki komutu çalıştırın:

${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py

Referanslar oluşturulduktan sonra, kaynak kodda yapılan ve VNDK kitaplığında uyumsuz bir ABI/API değişikliğine neden olan her değişiklik artık derleme hatasıyla sonuçlanıyor.

Belirli kitaplıklar için ABI referanslarını güncellemek üzere aşağıdaki komutu çalıştırın:

${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l <lib1> -l <lib2>

Örneğin, libbinder ABI referanslarını güncellemek için şunu çalıştırın:

${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder