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ç, ABI temsillerini toplayıp karşılaştırır mevcut çekirdek ikili programlarından (vmlinux+ GKI modülü). Bu ABI .stg dosyaları ve simge listeleridir. İlgili arayüz Bu gösterime Çekirdek Modülü Arayüzü adı verilir. (KMI). KMI'daki değişiklikleri izlemek ve azaltmak için bu araçları kullanabilirsiniz.

ABI izleme araçları AOSP'de geliştirilmiştir ve STG (veya libabigail inç Android 13 ve önceki sürümler) oluşturmak ve karşılaştırmak için temsil eder.

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, katkıda bulunulan değişikliklere ilişkin bilgiler de yer almaktadır geri dönelim.

Süreç

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

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

Aşağıdaki talimatlar, oluşturabileceğiniz çekirdek desteklenen araç zinciri (önceden oluşturulmuş Clang araç zinciri gibi) sağlar. 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, hatta 30.000'in üzerinde dışa aktarılan simgeler. Bunun yerine tedarikçi modülleri tarafından kullanılabilecek simgeler kök dizinde herkese açık bir şekilde saklanan bir simge listesi dosyaları grubunda açıkça listelenmektedir. örneğidir. Tüm simge listesi dosyalarındaki tüm simgelerin birleşimi kararlı olarak tutulan KMI sembolleri kümesini tanımlar. Örnek simge listesi dosyası : abi_gki_aarch64_db845c, için gereken simgeleri belirten DragonBoard 845c.

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 kullanıma sunulduktan sonra KMI tanımının parçası olan bir sembol listesinde olup ve simge listesinden çıkarılmamalı veya dal donduruldu.

Her Android Ortak Çekirdeği (ACK) KMI çekirdeği dalının kendi sembol grubu vardır listeler. Farklı KMI çekirdeği arasında ABI kararlılığı sağlamak için herhangi bir girişimde bulunulmaz dalları. Örneğin, android12-5.10 KMI'si şunlardan tamamen bağımsızdır: android13-5.10 için KMI.

ABI araçları, kararlılık için hangi arayüzlerin izlenmesi gerektiğini sınırlamak amacıyla KMI simge listelerini kullanır. İlgili içeriği oluşturmak için kullanılan ana simge listesi GKI çekirdek modüllerinin gerektirdiği sembolleri içerir. Satıcılar sağlandığından emin olmak için ek simge listelerinin gönderilmesi ve güncellenmesi ABI ile uyumluluk sağlamak için kullandıkları arayüzler. Örneğin, android13-5.15 için simge listelerinin listesini görmek isterseniz https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android bölümüne bakın.

Simge listesi, belirli bir tedarikçi veya cihaz için gerekli olduğu bildirilen simgeleri içerir. Araçların kullandığı tam liste, tüm bu araçların KMI simge listesi dosyaları. ABI araçları, her sembolün ayrıntılarını belirler. işlev imzası ve iç içe yerleştirilmiş veri yapılarını tanıtır.

KMI dondurulduğunda mevcut KMI arayüzlerinde değişiklik yapılmasına izin verilmez. Bu arayüzler kararlıdır. Ancak tedarikçi firmalar, eklemeler mevcut ABI'nin kararlılığını etkilemediği sürece KMI'ye diledikleri zaman sembol ekleyebilir. Yeni eklenenler sembolleri bir KMI simge listesinde belirtildiği anda sabit kalır. Çekirdek teyit edilemediği sürece listeden semboller kaldırılmamalıdır hiçbir cihazın bu sembole bağımlı bir şekilde gönderilmediği anlamına gelir.

Şu adresteki talimatları uygulayarak bir cihaz için KMI simge listesi oluşturabilirsiniz: Simge listeleriyle çalışma. Birçok iş ortağı, ACK başına bir sembol listesi gönderir ancak bu zorunlu bir gereklilik değildir. Bakıma yardımcı olacaksa birden fazla sembol listesi gönderebilirsiniz.

KMI'yı genişletin

KMI sembolleri ve ilgili yapılar kararlı olarak korunurken (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'nin kapsamını genişletmek için KMI'ye yeni veya KMI donmuş olsa bile dışa aktarılan mevcut çekirdek işlevlerinin yerine getirilmesini sağlar. Yeni çekirdek yamalar, KMI'yı ihlal etmedikleri takdirde de kabul edilebilir.

KMI kesintileri hakkında

Çekirdeklerde kaynaklar bulunur ve ikili programlar bu kaynaklardan oluşturulur. ABI tarafından izlenen çekirdek dalları, geçerli GKI'nın ABI temsilini içerir ABI (.stg dosyası biçiminde). İkili programlardan sonra (vmlinux, Image ve herhangi bir GKI modülü) oluşturulmuşsa dosyadan ABI temsili her zaman daha iyidir. Çekirdek kaynak dosyasında yapılan herhangi bir değişiklik, ikili programları ve çevirmesi, ayıklanan .stg öğelerini de etkiler. 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 kesintilerini yönetme

Ö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 zamanında ABI farklılıkları algılandı

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.

Sembol, sembol listesinde (android/abi_gki_aarch64) yoksa önce dosyanın dışa aktarıldığını ve EXPORT_SYMBOL_GPL(symbol_name) ve ardından ABI XML gösterimi ve simge listesi. Örneğin, aşağıdaki değişiklikler yeni Artımlı FS özelliğini android-12-5.10 dalına Sembol listesinin ve ABI XML temsilinin güncellenmesini içerir.

  • Özellik değişikliği örneği: aosp/1345659 adresinde bulabilirsiniz.
  • Sembol listesi örneği: aosp/1346742 adresinde bulabilirsiniz.
  • ABI XML değişiklik örneği aosp/1349377 adresindedir.

Sembol dışa aktarılmışsa (sizin tarafınızdan veya daha önce dışa aktarılmışsa) ancak kullanıyorsanız 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ğinizde hem de ACK'de KMI simge listesini güncelleyin (bkz. ABI temsilini güncelleyin). ACK'deki ABI XML ve simge listesini 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ıyla başa çıkabilirsiniz. Şunları kullanın: durumunuza en uygun yaklaşımı belirlemek için kullanabilirsiniz.

ABI Döküm Akış Grafiği

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

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

Mevcut ABI'da değişiklik yapmamak için elinizden geleni yapın. Birçok durumda ABI'yı etkileyen değişiklikleri kaldırmak için kodunuzu yeniden düzenleyin.

  • Yapı alanındaki değişiklikleri yeniden düzenleme Bir değişiklik, bir hata ayıklama özelliğinin ABI'sini değiştiriyorsa alanların etrafına (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 düzenleme. İş 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'yı 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. Aracın bulduğu sorunları gidererek başlayın.

ABI bulgularını yerel olarak yeniden oluşturabilirsiniz. Çekirdek ve ABI temsilini oluşturun.

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'sını 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. Kod değişikliklerini ACK'ye 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 kodu 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 ACK’ye ilk olarak seçilebilir. Örnek:

    • 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şılabilecek bir özellikle ilgiliyse ACK’ye olması gerektiği 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.

  • Çekirdek izole özellik saplaması (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'ye seçilerek yalnızca şunları içerecek şekilde kırpıldı: task_struct ve UA mülkleri arasındaki ABI farkını gidermek için mm_event_count. Ayrıca bu yama, mm_event_type enum listesini şunu içerecek şekilde günceller: son üyelere ulaşabilirsiniz.

  • 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şikliği (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ı, üretim çekirdeklerine CONFIG_NL80211_TESTMODE ekleyip GKI uyumluluğunu koruyabildi.

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

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 zamanında uygulanır ve eksik girişler işaretlenir.

Geliştirme amacıyla sembolün kırpılması (yani genellikle dışa aktarılan tüm simgeler kullanılabilir). Yerini bulmak için bu derlemeleri görmek için kernel_debug_aarch64 ci.android.com adresine gidin.

Modül sürümü oluşturmayı kullanarak KMI'yi zorunlu kılma

Genel Çekirdek Görüntüsü (GKI) çekirdekleri, çalışma zamanında KMI uyumluluğunu 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 örnek normal bir hatadır: module_layout() simgesi için CRC uyuşmazlığından dolayı modül yükleme süresi:

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ümü oluşturma aşağıdaki nedenlerle yararlıdır:

  • Modül sürümü oluşturma, veri yapısı görünürlüğündeki 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.

    fwnode struct device alanındaki değer. 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 birkaç nedenden dolayı sorunludur, şu şekilde ifade edilmektedir:

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

    • Gelecekteki 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 bozulduğu için stgdiff herhangi bir farklılık göstermeyecek dahili veri yapılarını mümkün olmayan şekillerde etkileyerek yalnızca ikili gösterim incelenerek yakalanabilir.

  • Mevcut bir modül daha sonraki bir tarihte yüklendiğinde KMI ile uyumsuz olarak kabul edilir yeni bir çekirdekle karşılaştırabilirsiniz. Modül sürümü oluşturma, çekirdekle KMI uyumlu olmayan bir modülü yanlışlıkla yüklemeyin. Bu denetim, hata ayıklaması zor çalışma zamanı sorunlarını ve gerçekleşebilecek çekirdek kilitlenmelerini KMI'de saptanmamış bir uyumsuzluktan kaynaklanmaktadır.

Modül sürümü oluşturmanın etkinleştirilmesi tüm bu sorunların önüne geçer.

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

stgdiff, diğer çekirdeklerle çekirdekler arasındaki CRC uyuşmazlıklarını ABI farklılıkları.

Ayrıca, CONFIG_MODVERSIONS özelliğinin etkin olduğu tam çekirdek derlemesi Module.symvers dosyası olarak yükleyebilirsiniz. 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. Varsa vmlinux tarafından dışa aktarılan herhangi bir simgedeki CRC değer farkı ve cihazınıza yüklediğiniz modüllerden biri tarafından kullanılıyorsa modül, yükleyin.

Tüm derleme yapılarına sahip değilseniz ancakvmlinux arasında bağlantı kurmak için, GKI çekirdeğinin ve çekirdeğinizin aşağıdaki komutu her iki çekirdekte de çalıştırarak ve çıkış:

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

Örneğin, aşağıdaki komut, module_layout için CRC değerini kontrol eder simge:

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ümler için GKI çekirdeğini derleme Ayrıca, cihaz çekirdeğinizde KBUILD_SYMTYPES=1 komutunun başına aşağıdaki komutta gösterildiği gibi, çekirdeği oluşturmak için kullanın:

    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. GKI'da .c dosyasının karşılık gelen .symtypes dosyası vardır ve cihaz çekirdeği derleme yapıları. 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 (potansiyel olarak ç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 farkları düzeltin.

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

Bir çekirdek, bir simgeyi veya veri türünü modüllere 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 sembol için UNKNOWN bulunur ve diğer çekirdekteki .symtypes dosyasında sembolün 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>

Bu simge için module.symtypes karşılaştırıldığında şu değer elde edilir: farklar:

 $ 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ğiniz UNKNOWN değerine sahipse ve GKI çekirdeği genişletilmiş görünüme sahipse çok düşük bir ihtimal), ardından en son Android Common Kernel'i .

Çoğu durumda, GKI çekirdeği UNKNOWN değerine sahiptir ancak çekirdeğiniz çekirdeğinizde yapılan değişikliklerden dolayı simgenin dahili ayrıntılarıdır. Bu çünkü çekirdekinizdeki dosyalardan biri, #include .

Çoğu zaman, çözüm yeni #include öğesini genksyms'dan 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. Başlık dosyasının en üstüne aşağıdaki kodu ekleyin:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. Modülün .c dosyasında CRC uyuşmazlığı olan #include satırlarının herhangi birinden önceki ilk satır olarak takip edin.

    #define CRC_CATCH 1
    
  4. Modülünüzü derleyin. Sonuç olarak ortaya çıkan derleme zamanı hatası, bu CRC uyuşmazlığına neden olan #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, yoksa GKI çekirdeğinde yoktur.

  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ığının nedeninin veya kapsamdaki gerçek değişikliklerden (eklemeler, kaldırmalar veya değişiklikler) veri türünün kendisi.

Örneğin, çekirdeğinizde aşağıdaki değişikliğin yapılması çeşitli CRC'ye neden olur dolaylı olarak etkilenen çok sayıda simge olduğu için uyuşmazlıklar:

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

devm_of_platform_populate() için bir CRC uyuşmazlığı var.

Bu simgenin .symtypes dosyalarını karşılaştırırsanız simge aşağıdaki gibi görünebilir:

 $ 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 kaydetme listesini inceleyin. Muhtemelen aradığınız ilk taahhüttür. Uygun değilse kaydı bulana kadar bekleyin.

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