Android çekirdek ABI izleme

Android çekirdeklerinin çekirdek içi ABI'sini stabilize etmek için Android 11 ve sonraki sürümlerde bulunan uygulama ikili arayüzü (ABI) izleme araçlarını kullanabilirsiniz. Araçlar, mevcut çekirdek ikililerinden (vmlinux+ GKI modülleri) ABI temsillerini toplayıp karşılaştırır. Bu ABI temsilleri, .stg dosyaları ve simge listeleridir. Temsilasyonun görünüm sunduğu arayüze çekirdek modülü arayüzü (KMI) denir. KMI'deki değişiklikleri izlemek ve azaltmak için araçları kullanabilirsiniz.

ABI izleme araçları AOSP'de geliştirilir ve temsiller oluşturmak ve karşılaştırmak için STG'yi (veya Android 13 ve önceki sürümlerde libabigail) kullanır.

Bu sayfada, araç seti, ABI temsillerini toplama ve analiz etme süreci ve çekirdek içi ABI'ye kararlılık sağlamak için bu tür temsillerin kullanımı açıklanmaktadır. Bu sayfada, Android çekirdeklerine değişiklik katkıda bulunma hakkında da bilgi verilmektedir.

Süreç

Çekirdeğin ABI'sini analiz etmek için birden fazla adım gerekir. Bu adımların çoğu otomatikleştirilebilir:

  1. Çekirdeği ve ABI temsilini derleyin.
  2. Derleme ile referans arasındaki ABI farklılıklarını analiz edin.
  3. ABI temsilini (gerekirse) güncelleyin.
  4. Sembol listeleriyle çalışma

Aşağıdaki talimatlar, desteklenen bir araç zinciri (önceden derlenmiş Clang araç zinciri gibi) kullanarak derleyebileceğiniz tüm çekirdekler için geçerlidir. repo manifests, tüm Android ortak çekirdek dalları ve cihaza özgü çeşitli çekirdekler için kullanılabilir. Analiz için çekirdek dağıtımı oluştururken doğru araç zincirinin kullanılmasını sağlar.

Sembol listeleri

KMI,çekirdekteki tüm simgeleri veya dışa aktarılan 30.000'den fazla simgenin tamamını içermez. Bunun yerine, tedarikçi modülleri tarafından kullanılabilen semboller, çekirdek ağacında (Android 15 ve önceki sürümlerde gki/{ARCH}/symbols/* veya android/abi_gki_{ARCH}_*) herkese açık olarak tutulan bir dizi sembol listesi dosyasında açıkça listelenir. Tüm simge listesi dosyalarındaki tüm simgelerin birleşimi, sabit olarak tutulan KMI simge grubunu tanımlar. DragonBoard 845c için gereken sembolleri bildiren gki/aarch64/symbols/db845c, örnek bir simge listesi dosyasıdır.

Yalnızca bir simge listesinde listelenen simgeler ve ilgili yapıları ile tanımları KMI'nın bir parçası olarak kabul edilir. İhtiyacınız olan semboller yoksa simge listelerinizde değişiklik yayınlayabilirsiniz. Yeni arayüzler bir simge listesine eklendikten ve KMI açıklamasının bir parçası olduktan sonra kararlı olarak korunur ve dal dondurulduktan sonra simge listesinden kaldırılmamalı veya değiştirilmemelidir.

Her Android Ortak Çekirdek (ACK) KMI çekirdek dalının kendi simge listesi vardır. Farklı KMI çekirdek dalları arasında ABI kararlılığı sağlamaya çalışılmaz. Örneğin, android12-5.10 için KMI, android13-5.10 için KMI'den tamamen bağımsızdır.

ABI araçları, kararlılık için hangi arayüzlerin izlenmesi gerektiğini sınırlamak amacıyla KMI simge listelerini kullanır. Tedarikçi firmaların, kullandıkları arayüzlerin ABI uyumluluğunu korumasını sağlamak için kendi simge listelerini gönderip güncellemeleri beklenir. Örneğin, android16-6.12 çekirdeği için simge listelerinin listesini görmek isterseniz https://android.googlesource.com/kernel/common/+/refs/heads/android16-6.12/gki/aarch64/symbols

Simge listesi, belirli bir tedarikçi veya cihaz için gerekli olduğu bildirilen simgeleri içerir. Araçlar tarafından kullanılan tam liste, tüm KMI simge listesi dosyalarının birleşimidir. ABI araçları, işlev imzası ve iç içe yerleştirilmiş veri yapıları da dahil olmak üzere her bir sembolün ayrıntılarını belirler.

KMI dondurulduğunda mevcut KMI arayüzlerinde değişiklik yapılmasına izin verilmez. Bu arayüzler kararlıdır. Ancak satıcılar, eklemeler mevcut ABI'nin kararlılığını etkilemediği sürece KMI'ye diledikleri zaman sembol ekleyebilir. Yeni eklenen semboller, bir KMI sembol listesi tarafından belirtildiği anda sabit olarak korunur. Hiçbir cihazın bu sembolün bağımlılığını içermediği doğrulanmadığı sürece semboller bir çekirdek listesinden kaldırılmamalıdır.

Sembol listeleriyle çalışma başlıklı makaledeki talimatları kullanarak bir cihaz için KMI simge listesi oluşturabilirsiniz. Birçok iş ortağı, ACK başına bir simge listesi gönderir ancak bu zorunlu bir koşul değildir. Bakım konusunda yardımcı olması için birden fazla simge listesi gönderebilirsiniz.

KMI'yı genişletin

KMI sembolleri ve ilgili yapılar kararlı olarak korunur (yani dondurulmuş bir KMI'ye sahip çekirdekteki kararlı arayüzleri bozan değişiklikler kabul edilemez). GKI çekirdeği, yılın ilerleyen dönemlerinde piyasaya sürülen cihazların KMI dondurulmadan önce tüm bağımlılıkları tanımlaması gerekmemesi için uzantılara açık kalır. KMI'yi genişletmek için KMI dondurulmuş olsa bile yeni veya mevcut dışa aktarılan çekirdek işlevleri için KMI'ye yeni simgeler ekleyebilirsiniz. KMI'yi bozmayan yeni çekirdek yamaları da kabul edilebilir.

KMI kesintileri hakkında

Çekirdeklerin kaynakları vardır ve ikili dosyalar bu kaynaklardan derlenir. ABI tarafından izlenen çekirdek dalları, mevcut GKI ABI'sinin ABI temsilini (.stg dosyası biçiminde) içerir. İkili dosyalar (vmlinux, Image ve tüm GKI modülleri) oluşturulduktan sonra, ikili dosyalardan bir ABI temsili ayıklanabilir. Bir çekirdek kaynak dosyasında yapılan herhangi bir değişiklik, ikili dosyaları etkileyebilir ve bu da ayıklanan .stg dosyasını etkileyebilir. AbiAnalyzer analizörü, taahhüde bağlanmış .stg dosyasını derleme yapılarından ayıklanan dosyayla karşılaştırır ve anlamsal bir fark bulursa Gerrit'te değişiklik için Lint-1 etiketi ayarlar.

ABI'de kesintileri ele alma

Örneğin, aşağıdaki yama çok belirgin bir ABI kesintisi oluşturur:

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 42786e6364ef..e15f1d0f137b 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -657,6 +657,7 @@ struct mm_struct {
                ANDROID_KABI_RESERVE(1);
        } __randomize_layout;

+       int tickle_count;
        /*
         * The mm_cpumask needs to be at the end of mm_struct, because it
         * is dynamically sized based on nr_cpu_ids.

Bu yamanın uygulandığı derleme ABI'sini çalıştırdığınızda araç, sıfır olmayan bir hata koduyla çıkar ve aşağıdakine benzer bir ABI farkı bildirir:

function symbol 'struct block_device* I_BDEV(struct inode*)' changed
  CRC changed from 0x8d400dbd to 0xabfc92ad

function symbol 'void* PDE_DATA(const struct inode*)' changed
  CRC changed from 0xc3c38b5c to 0x7ad96c0d

function symbol 'void __ClearPageMovable(struct page*)' changed
  CRC changed from 0xf489e5e8 to 0x92bd005e

... 4492 omitted; 4495 symbols have only CRC changes

type 'struct mm_struct' changed
  byte size changed from 992 to 1000
  member 'int tickle_count' was added
  member 'unsigned long cpu_bitmap[0]' changed
    offset changed by 64

Derleme sırasında algılanan ABI farklılıkları

Hataların en yaygın nedeni, bir sürücünün çekirdekteki ve simge listelerinin hiçbirinde bulunmayan yeni bir simge kullanmasıdır.

Simge, simge listenize dahil değilse önce EXPORT_SYMBOL_GPL(symbol_name) ile dışa aktarıldığından emin olmanız, ardından simge listesini ve ABI temsilini güncellemeniz gerekir. Örneğin, aşağıdaki değişiklikler android-12-5.10 dalına yeni Artımlı FS özelliğini ekler. Bu özellik, simge listesini ve ABI temsilini güncellemeyi içerir.

Simge dışa aktarılmışsa (sizin tarafınızdan veya daha önce dışa aktarılmışsa) ancak başka bir sürücü tarafından kullanılmıyorsa aşağıdakine benzer bir derleme hatası alabilirsiniz.

Comparing the KMI and the symbol lists:
+ build/abi/compare_to_symbol_list out/$BRANCH/common/Module.symvers out/$BRANCH/common/abi_symbollist.raw
ERROR: Differences between ksymtab and symbol list detected!
Symbols missing from ksymtab:
Symbols missing from symbol list:
 - simple_strtoull

Sorunu çözmek için hem çekirdeğinize hem de ACK'ye KMI simge listesini güncelleyin (ABI temsilini güncelleme bölümüne bakın). ACK'deki bir simge listesini ve ABI temsilini güncelleme örneği için aosp/1367601 adresine bakın.

Çekirdek ABI'si bozulmalarını çözme

ABI'yi değiştirmeyecek şekilde kodu yeniden düzenleyerek veya ABI temsilini güncelleyerek çekirdek ABI'si bozulmalarını giderebilirsiniz. Durumunuza en uygun yaklaşımı belirlemek için aşağıdaki grafiği kullanın.

ABI Kesintisi Akış Şeması

Şekil 1. ABI kesintisi çözümü

ABI değişikliklerini önlemek için kodu yeniden yapılandırın

Mevcut ABI'yi değiştirmemek için elinizden geleni yapın. Çoğu durumda, ABI'yi etkileyen değişiklikleri kaldırmak için kodunuzu yeniden yapılandırabilirsiniz.

  • Yapı alanındaki değişiklikleri yeniden düzenleme Bir değişiklik, bir hata ayıklama özelliğinin ABI'sini değiştiriyorsa alanlara (yapılar ve kaynak referanslarında) bir #ifdef ekleyin ve #ifdef için kullanılan CONFIG'nin üretim defconfig ve gki_defconfig için devre dışı olduğundan emin olun. Bir hata ayıklama yapılandırmasının, ABI'yi bozmadan bir yapıya nasıl eklenebileceğine dair bir örnek için bu yama grubuna bakın.

  • Temel çekirdeği değiştirmemek için özellikleri yeniden yapılandırın. İş ortağı modüllerini desteklemek için ACK'ye yeni özellikler eklenmesi gerekiyorsa çekirdek ABI'sini değiştirmemek için değişikliğin ABI bölümünü yeniden yapılandırmayı deneyin. Çekirdek ABI'sini değiştirmeden ek özellikler eklemek için mevcut çekirdek ABI'sini kullanma örneği için aosp/1312213 adresine bakın.

Android Gerrit'te bozuk ABI'yi düzeltme

Kernel ABI'yi kasıtlı olarak bozmadıysanız ABI izleme araçları tarafından sağlanan kılavuzu kullanarak incelemeniz gerekir. Kesintinin en yaygın nedenleri, değiştirilen veri yapıları ve ilişkili simge CRC değişiklikleri ya da yukarıdakilerden herhangi birine yol açan yapılandırma seçeneği değişiklikleridir. Araç tarafından bulunan sorunları gidererek başlayın.

ABI bulgularını yerel olarak yeniden oluşturabilirsiniz. Çekirdeği ve ABI temsilini oluşturma başlıklı makaleyi inceleyin.

Lint-1 etiketleri hakkında

Dondurulmuş veya nihai KMI içeren bir dala değişiklik yüklerseniz değişikliklerin kararlı ABI'yi uyumsuz bir şekilde etkilemediğinden emin olmak için değişiklikler AbiAnalyzer'ten geçmelidir. Bu işlem sırasında AbiAnalyzer, derleme sırasında oluşturulan ABI raporunu (normal derlemeyi ve ardından bazı ABI ayıklama ve karşılaştırma adımlarını gerçekleştiren genişletilmiş bir derleme) arar.

AbiAnalyzer boş olmayan bir rapor bulursa Lint-1 etiketini ayarlar ve değişiklik, çözülene kadar (yama grubu Lint+1 etiketi alana kadar) gönderilmesi engellenir.

Çekirdek ABI'sini güncelleme

ABI'nin değiştirilmesi kaçınılmazsa kod değişikliklerinizi, ABI temsilini ve simge listesini ACK'ye uygulamanız gerekir. Lint'in -1 değerini kaldırmasını ve GKI uyumluluğunu bozmamasını sağlamak için aşağıdaki adımları uygulayın:

  1. ACK'ye kod değişikliklerini yükleyin.

  2. Yama grubu için Code-Review +2 almayı bekleyin.

  3. Referans ABI temsilini güncelleyin.

  4. Kod değişikliklerinizi ve ABI güncelleme değişikliğini birleştirin.

ABI kod değişikliklerini ACK'ye yükleme

ACK ABI'nin güncellenmesi, yapılan değişikliğin türüne bağlıdır.

  • Bir ABI değişikliği, CTS veya VTS testlerini etkileyen bir özellikle ilgiliyse değişiklik genellikle olduğu gibi ACK için seçilebilir. Örneğin:

    • Sesin çalışması için aosp/1289677 sürümünün yüklü olması gerekir.
    • USB'nin çalışması için aosp/1295945 sürümünün yüklü olması gerekir.
  • ABI değişikliği, ACK ile paylaşılabilen bir özellik içinse bu değişiklik, ACK'ye olduğu gibi seçilebilir. Örneğin, aşağıdaki değişiklikler CTS veya VTS testi için gerekli değildir ancak ACK ile paylaşılabilir:

  • Bir ABI değişikliği, ACK'ye dahil edilmesi gerekmeyen yeni bir özellik sunuyorsa aşağıdaki bölümde açıklandığı gibi bir taslak kullanarak simgeleri ACK'ye ekleyebilirsiniz.

ACK için taslakları kullanma

Stub'lar yalnızca ACK'ye fayda sağlamayan temel çekirdek değişiklikleri (ör. performans ve güç değişiklikleri) için gerekli olmalıdır. Aşağıdaki listede, GKI için ACK'deki taslaklar ve kısmi seçmeler örnekleri ayrıntılı olarak açıklanmıştır.

  • Core-isolate özellik stub'ı (aosp/1284493). ACK'deki özellikler gerekli değildir ancak modüllerinizin bu sembolleri kullanabilmesi için ACK'de sembollerin bulunması gerekir.

  • Tedarikçi modülü için yer tutucu simgesi (aosp/1288860).

  • İşlem başına mm etkinlik izleme özelliğinin yalnızca ABI'de kullanılabilen seçkin bir bölümü (aosp/1288454). Orijinal yama, ACK için özenle seçildi ve ardından yalnızca task_struct ve mm_event_count için ABI farkını çözmek üzere gerekli değişiklikleri içerecek şekilde kısaltıldı. Bu yama, mm_event_type enum'unu nihai üyeleri içerecek şekilde de günceller.

  • Yalnızca yeni ABI alanlarının eklenmesini gerektiren termal yapı ABI değişikliklerinin kısmi olarak seçilmesi.

    • aosp/1255544 yaması, iş ortağı çekirdeği ile ACK arasındaki ABI farklılıklarını çözdü.

    • aosp/1291018 yaması, önceki yamanın GKI testi sırasında bulunan işlevsel sorunları düzeltti. Düzeltme, sensör parametresi yapısını tek bir sensöre birden fazla termal bölge kaydetmek için başlatmayı içeriyordu.

  • CONFIG_NL80211_TESTMODE ABI değişiklikleri (aosp/1344321). Bu yama, ABI için gerekli yapı değişikliklerini ekledi ve ek alanların işlevsel farklılıklara neden olmadığından emin oldu. Böylece iş ortakları, CONFIG_NL80211_TESTMODE'ü üretim çekirdeklerine ekleyip GKI uyumluluğunu koruyabildi.

Çalışma zamanında KMI'yı zorunlu kılma

GKI çekirdekleri, dışa aktarılan sembolleri (EXPORT_SYMBOL_GPL() kullanılarak dışa aktarılan semboller gibi) bir sembol listesinde listelenenlerle sınırlayan TRIM_UNUSED_KSYMS=y ve UNUSED_KSYMS_WHITELIST=<union of all symbol lists> yapılandırma seçeneklerini kullanır. Diğer tüm semboller dışa aktarılmaz ve dışa aktarılmamış bir sembol gerektiren modülün yüklenmesi reddedilir. Bu kısıtlama derleme sırasında uygulanır ve eksik girişler işaretlenir.

Geliştirme amacıyla, simge kırpma içermeyen bir GKI çekirdek derlemesi kullanabilirsiniz (yani genellikle dışa aktarılan tüm simgeler kullanılabilir). Bu derlemeleri bulmak için ci.android.com adresinde kernel_debug_aarch64 derlemelerini arayın.

Modül sürümlendirmesini kullanarak KMI'yi zorunlu kılma

Genel Çekirdek Görüntüsü (GKI) çekirdekleri, KMI uyumluluğunu çalışma zamanında zorunlu kılmak için ek bir önlem olarak modül sürümlendirmesini (CONFIG_MODVERSIONS) kullanır. Modül sürümlendirmesi, bir modülün beklenen KMI vmlinux KMI ile eşleşmezse modül yükleme sırasında döngüsel artıklık kontrolü (CRC) eşleşmemesi hatalarına neden olabilir. Örneğin, aşağıdaki hata, module_layout() sembolünün CRC uyuşmazlığı nedeniyle modül yükleme zamanında ortaya çıkan tipik bir hatadır:

init: Loading module /lib/modules/kernel/.../XXX.ko with args ""
XXX: disagrees about version of symbol module_layout
init: Failed to insmod '/lib/modules/kernel/.../XXX.ko' with args ''

Modül sürüm oluşturmanın kullanım alanları

Modül sürümlendirme aşağıdaki nedenlerden dolayı kullanışlıdır:

  • Modül sürümlendirmesi, veri yapısı görünürlüğünde yapılan değişiklikleri yakalar. Modüller opak veri yapılarını (yani KMI'nın parçası olmayan veri yapılarını) değiştirirse yapıda daha sonra yapılan değişikliklerden sonra bozulurlar.

    Örneğin, struct device içindeki fwnode alanını ele alalım. Bu alan, modüllerin device->fw_node alanlarında değişiklik yapamamaları veya boyutu hakkında varsayımlarda bulunmamaları için modüller tarafından opak OLMALIDIR.

    Ancak bir modül <linux/fwnode.h> (doğrudan veya dolaylı olarak) içeriyorsa struct device içindeki fwnode alanı artık modül için opak değildir. Modül daha sonra device->fwnode->dev veya device->fwnode->ops'te değişiklik yapabilir. Bu senaryo, aşağıdaki gibi çeşitli nedenlerden dolayı sorunludur:

    • Çekirdek çekirdek kodunun dahili veri yapıları hakkında yaptığı varsayımları bozabilir.

    • Gelecekte yapılacak bir çekirdek güncellemesi struct fwnode_handle'ü (fwnode veri türü) değiştirirse modül artık yeni çekirdekle çalışmaz. Ayrıca modül, dahili veri yapılarını doğrudan manipüle ederek KMI'yı bozduğundan stgdiff herhangi bir fark göstermez. Bu manipülasyon, yalnızca ikili gösterimi inceleyerek yakalanamaz.

  • Mevcut bir modül, uyumlu olmayan yeni bir çekirdek tarafından daha sonra yüklendiğinde KMI ile uyumlu değildir. Modül sürümlendirme, çekirdekle KMI uyumlu olmayan bir modülün yanlışlıkla yüklenmesini önlemek için çalışma zamanında bir kontrol ekler. Bu kontrol, KMI'de algılanmayan bir uyumsuzluktan kaynaklanabilecek, hata ayıklamanın zor olduğu çalışma zamanı sorunlarını ve çekirdek kilitlenmelerini önler.

Modül sürümlendirmeyi etkinleştirmek tüm bu sorunları önler.

Cihazı başlatmadan CRC uyuşmazlıklarını kontrol etme

stgdiff, diğer ABI farklılıklarının yanı sıra çekirdekler arasındaki CRC uyuşmazlıklarını karşılaştırır ve raporlar.

Ayrıca, CONFIG_MODVERSIONS etkinken yapılan tam çekirdek derlemesi, normal derleme sürecinin bir parçası olarak bir Module.symvers dosyası oluşturur. Bu dosyada, çekirdek (vmlinux) ve modüller tarafından dışa aktarılan her simge için bir satır bulunur. Her satır; CRC değeri, simge adı, simge ad alanı, simgeyi dışa aktaran vmlinux veya modül adı ve dışa aktarma türü (örneğin, EXPORT_SYMBOL ve EXPORT_SYMBOL_GPL) içerir.

vmlinux tarafından dışa aktarılan simgelerde CRC farklılıkları olup olmadığını kontrol etmek için GKI derlemesi ile derlemeniz arasındaki Module.symvers dosyalarını karşılaştırabilirsiniz. vmlinux tarafından dışa aktarılan herhangi bir simgede CRC değeri farkı varsa ve bu simge cihazınıza yüklediğiniz modüllerden biri tarafından kullanılıyorsa modül yüklenmez.

Tüm derleme yapılarını kullanamıyorsanız ancak GKI çekirdeği ve çekirdeğinizin vmlinux dosyalarına sahipseniz aşağıdaki komutu her iki çekirdekte de çalıştırıp çıktıları karşılaştırarak belirli bir sembolün CRC değerlerini karşılaştırabilirsiniz:

nm <path to vmlinux>/vmlinux | grep __crc_<symbol name>

Örneğin, aşağıdaki komut module_layout sembolünün CRC değerini kontrol eder:

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

CRC uyuşmazlıklarını çözme

Bir modülü yüklerken CRC uyuşmazlığını çözmek için aşağıdaki adımları uygulayın:

  1. Aşağıdaki komutta gösterildiği gibi --kbuild_symtypes seçeneğini kullanarak GKI çekirdeğini ve cihaz çekirdeğinizi oluşturun:

    tools/bazel run --kbuild_symtypes //common:kernel_aarch64_dist

    Bu komut, her .o dosyası için bir .symtypes dosyası oluşturur. Ayrıntılar için Kleaf'teki KBUILD_SYMTYPES bölümüne bakın.

    Android 13 ve önceki sürümlerde, GKI çekirdeğini ve cihaz çekirdeğinizi oluşturmak için aşağıdaki komutta gösterildiği gibi çekirdeği oluşturmak için kullandığınız komutun başına KBUILD_SYMTYPES=1 ekleyerek oluşturun:

    KBUILD_SYMTYPES=1 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh

    build_abi.sh, kullanıldığında KBUILD_SYMTYPES=1 işareti zaten dolaylı olarak ayarlanmıştır.

  2. Aşağıdaki komutu kullanarak CRC uyuşmazlığı olan sembolün dışa aktarıldığı .c dosyasını bulun:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
  3. .c dosyasının GKI'da ve cihaz çekirdek derleme yapılarında karşılık gelen bir .symtypes dosyası vardır. Aşağıdaki komutları kullanarak .c dosyasını bulun:

    cd out/$BRANCH/common && ls -1 kernel/module.*
    kernel/module.o
    kernel/module.o.symversions
    kernel/module.symtypes

    .c dosyasının özellikleri şunlardır:

    • .c dosyasının biçimi, simge başına bir (muhtemelen çok uzun) satırdır.

    • Satırın başındaki [s|u|e|etc]#, sembolün veri türü [struct|union|enum|etc] olduğunu gösterir. Örnek:

      t#bool typedef _Bool bool
      
    • Satırın başında # ön eklerinin eksik olması, sembolün bir işlev olduğunu gösterir. Örnek:

      find_module s#module * find_module ( const char * )
      
  4. İki dosyayı karşılaştırın ve tüm farklılıkları düzeltin.

1. durum: Veri türü görünürlüğünden kaynaklanan farklılıklar

Bir çekirdek, bir simgeyi veya veri türünü modüller için opak tutarken diğer çekirdek bunu yapmazsa bu fark, iki çekirdeğin .symtypes dosyaları arasında görünür. Çekirdeklerden birindeki .symtypes dosyasında simge için UNKNOWN bulunur ve diğer çekirdekteki .symtypes dosyasında simgenin veya veri türünün genişletilmiş görünümü bulunur.

Örneğin, aşağıdaki satırı çekirdeğinize ait include/linux/device.h dosyasına eklemek CRC uyuşmazlıklarına neden olur. Bunlardan biri module_layout() içindir:

 #include <linux/fwnode.h>

Söz konusu simgenin module.symtypes değerini karşılaştırdığımızda aşağıdaki farklılıkları görürüz:

 $ diff -u <GKI>/kernel/module.symtypes <your kernel>/kernel/module.symtypes
  --- <GKI>/kernel/module.symtypes
  +++ <your kernel>/kernel/module.symtypes
  @@ -334,12 +334,15 @@
  ...
  -s#fwnode_handle struct fwnode_handle { UNKNOWN }
  +s#fwnode_reference_args struct fwnode_reference_args { s#fwnode_handle * fwnode ; unsigned int nargs ; t#u64 args [ 8 ] ; }
  ...

Çekirdeğinizin değeri UNKNOWN ise ve GKI çekirdeğinde sembolün genişletilmiş görünümü varsa (çok olası değildir) en son GKI çekirdek tabanını kullanmanız için en son Android Ortak Çekirdeği'ni çekirdeğinizle birleştirin.

Çoğu durumda, GKI çekirdeği UNKNOWN değerine sahiptir ancak çekirdeğinizde yapılan değişiklikler nedeniyle çekirdeğiniz sembolün dahili ayrıntılarını içerir. Bunun nedeni, çekirdeğinize ait dosyalardan birinin GKI çekirdeğinde bulunmayan bir #include eklemesidir.

Çoğu zaman, çözüm yeni #include öğesini genksyms'ten gizlemekle sınırlıdır.

#ifndef __GENKSYMS__
#include <linux/fwnode.h>
#endif

Aksi takdirde, farka neden olan #include değerini belirlemek için aşağıdaki adımları uygulayın:

  1. Bu farkı içeren simgeyi veya veri türünü tanımlayan başlık dosyasını açın. Örneğin, include/linux/fwnode.h için struct fwnode_handle değerini düzenleyin.

  2. Üstbilgi dosyasının en üstüne aşağıdaki kodu ekleyin:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. CRC uyuşmazlığı olan modülün .c dosyasına, #include satırlarından önce ilk satır olarak aşağıdakileri ekleyin.

    #define CRC_CATCH 1
    
  4. Modülünüzü derleyin. Sonuç olarak ortaya çıkan derleme zamanı hatası, bu CRC uyuşmazlığına yol açan #include üstbilgi dosyası zincirini gösterir. Örnek:

    In file included from .../drivers/clk/XXX.c:16:`
    In file included from .../include/linux/of_device.h:5:
    In file included from .../include/linux/cpu.h:17:
    In file included from .../include/linux/node.h:18:
    .../include/linux/device.h:16:2: error: "Included from here"
    #error "Included from here"
    

    Bu #include zincirindeki bağlantılardan biri, çekirdeğinizde yapılan ve GKI çekirdeğinde bulunmayan bir değişiklikten kaynaklanıyor.

  5. Değişikliği tanımlayın, çekirdeğinizde geri alın veya ACK'ye yükleyip birleştirin.

2. durum: Veri türü değişikliklerinden kaynaklanan farklılıklar

Bir simge veya veri türü için CRC uyuşmazlığı, görünürlüğdeki bir farklılıktan kaynaklanmıyorsa veri türünde yapılan gerçek değişikliklerden (eklemeler, kaldırmalar veya değişiklikler) kaynaklanır.

Örneğin, çekirdeğinizde aşağıdaki değişikliği yapmak birçok sembol bu tür bir değişiklikten dolaylı olarak etkilendiği için birkaç CRC uyuşmazlığına neden olur:

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
  --- a/include/linux/iommu.h
  +++ b/include/linux/iommu.h
  @@ -259,7 +259,7 @@ struct iommu_ops {
     void (*iotlb_sync)(struct iommu_domain *domain);
     phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova);
     phys_addr_t (*iova_to_phys_hard)(struct iommu_domain *domain,
  -        dma_addr_t iova);
  +        dma_addr_t iova, unsigned long trans_flag);
     int (*add_device)(struct device *dev);
     void (*remove_device)(struct device *dev);
     struct iommu_group *(*device_group)(struct device *dev);

Bir CRC uyuşmazlığı devm_of_platform_populate() içindir.

Söz konusu simgenin .symtypes dosyalarını karşılaştırırsanız bu dosyaların görünümü şöyle olabilir:

 $ diff -u <GKI>/drivers/of/platform.symtypes <your kernel>/drivers/of/platform.symtypes
  --- <GKI>/drivers/of/platform.symtypes
  +++ <your kernel>/drivers/of/platform.symtypes
  @@ -399,7 +399,7 @@
  ...
  -s#iommu_ops struct iommu_ops { ... ; t#phy
  s_addr_t ( * iova_to_phys_hard ) ( s#iommu_domain * , t#dma_addr_t ) ; int
    ( * add_device ) ( s#device * ) ; ...
  +s#iommu_ops struct iommu_ops { ... ; t#phy
  s_addr_t ( * iova_to_phys_hard ) ( s#iommu_domain * , t#dma_addr_t , unsigned long ) ; int ( * add_device ) ( s#device * ) ; ...

Değiştirilen türü belirlemek için aşağıdaki adımları uygulayın:

  1. Kaynak kodunda (genellikle .h dosyalarında) sembolün tanımını bulun.

    • Çekirdeğinizle GKI çekirdeği arasındaki simge farklılıkları için aşağıdaki komutu çalıştırarak commit'i bulun:
    git blame
    • Silinen simgeler (bir simgenin bir ağaçta silindiği ve diğer ağaçta da silinmesini istediğiniz durumlar) için satırı silen değişikliği bulmanız gerekir. Satırın silindiği ağaçta aşağıdaki komutu kullanın:
    git log -S "copy paste of deleted line/word" -- <file where it was deleted>
  2. Değişikliği veya silme işlemini bulmak için döndürülen taahhüt listesini inceleyin. Muhtemelen aradığınız ilk taahhüttür. Bulamazsanız listeyi gözden geçirerek kaydetmeyi bulun.

  3. Değişikliği belirledikten sonra çekirdeğinizde geri alın veya ACK'ye yükleyip birleştirin.