Android çekirdeği ABI izlemesi

Android çekirdeklerinin çekirdek içi ABI'sini sabitlemek için Android 11 ve sonraki sürümlerde kullanılabilen uygulama ikili arayüzü (ABI) izleme araçlarını kullanabilirsiniz. Araç, 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 bu 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 güncelleyin (gerekirse).
  4. Sembol listeleriyle çalışın.

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, hatta dışa aktarılan 30.000'den fazla sembolün hepsini içermez. Bunun yerine, tedarikçi modülleri tarafından kullanılabilen semboller, çekirdek ağacının kökünde 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. Örnek sembol listesi dosyası, DragonBoard 845c için gerekli simgeleri açıklayan abi_gki_aarch64_db845c 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. KMI açıklamasının bir parçası olan yeni arayüzler, simge listesinde yer aldıktan sonra kararlı olarak korunur ve simge listesinden kaldırılmamalı veya dal dondurulduktan sonra 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. Ana simge listesi, GKI çekirdek modüllerinin gerektirdiği sembolleri içerir. Tedarikçi firmaların, güvendikleri arayüzlerin ABI uyumluluğunu korumasını sağlamak için ek simge listeleri göndermesi ve güncellemesi beklenir. Ö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 tarafından kullanılan tüm KMI simge listesi dosyalarının birleşiminden yararlanılır. ABI araçları, işlev imzası ve iç içe yerleştirilmiş veri yapıları da dahil olmak üzere her 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 eklemeler mevcut ABI'nın kararlılığını etkilemediği sürece tedarikçiler dilediği zaman KMI'ya 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çerecek şekilde gönderilmediği doğrulanmadığı sürece semboller bir çekirdek listesinden kaldırılmamalıdır.

Simge 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 sembol listesi gönderir ancak bu zorunlu bir gereklilik 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 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'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 oluşturulur. 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üt edilen .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 oldukça bariz bir ABI kesintisini ortaya çıkarmıştır:

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, simge listesinde (android/abi_gki_aarch64) yoksa önce EXPORT_SYMBOL_GPL(symbol_name) ile dışa aktarıldığını doğrulamanız, ardından ABI XML gösterimini ve simge listesini 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 XML 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 çekirdek hem de ACK'deki KMI simge listesini güncelleyin (ABI temsilini güncelleme bölümüne bakın). ACK'de ABI XML ve simge listesini güncellemeyle ilgili bir örnek için aosp/1367601 adresine bakın.

Çekirdek ABI kesintilerini çözme

ABI'yi değiştirmeyecek şekilde kodu yeniden düzenleyerek veya ABI temsilini güncelleyerek çekirdek ABI'si bozulmalarıyla başa çıkabilirsiniz. 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'da değişiklik yapmamak 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 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 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. Çekirdek ve ABI temsilini oluşturma bölümüne bakın.

Lint-1 etiketleri hakkında

Dondurulmuş veya kesinleşmiş bir KMI içeren bir dala değişiklik yüklerseniz değişikliklerin kararlı ABI'yı uyumsuz bir şekilde etkilememesi için değişikliklerin AbiAnalyzer tarafından iletilmesi gerekir. 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önderilemez.

Çekirdek ABI'sını güncelleme

ABI'da değişiklik yapılması kaçınılmazsa kod değişikliklerinizi, ABI temsilini ve simge listesini ACK'ye uygulamanız gerekir. Lint'in -1'i kaldırmasını ve GKI uyumluluğunu bozmamasını sağlamak için şu 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 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.
  • ACK ile paylaşılabilen bir özellik için ABI değişikliği söz konusuysa bu değişiklik ACK'ye olduğu gibi seçilebilir. Örneğin, CTS veya VTS testi için aşağıdaki değişiklikler 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 saplama kullanın

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 taslağı (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 sıralamasını son ü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 düzeltme eki, iş ortağının çekirdeği ile ACK arasındaki ABI farklılıklarını çözmüştür.

    • aosp/1291018 yaması, önceki yamanın GKI testi sırasında bulunan işlevsel sorunları düzeltti. Bu çözüm, tek bir sensöre birden fazla termal alt bölge kaydetmek için sensör parametresi struct'ın başlatılmasını 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 olmamasını sağladı. Böylece iş ortakları, üretim çekirdeklerine CONFIG_NL80211_TESTMODE öğesini dahil ederken GKI uygunluğunu korudu.

Çalışma zamanında KMI'yi 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 semboller 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. Bir modülün beklenen KMI'si vmlinux KMI ile eşleşmiyorsa modül sürümü oluşturma, modül yükleme zamanında döngüsel yedeklilik kontrolü (CRC) uyuşmazlığı hatası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'nin parçası olmayan veri yapıları) değiştirirse yapıda daha sonra yapılacak 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ıyla ilgili varsayımlarını 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, dahili veri yapılarını doğrudan manipüle ederek KMI'yı bozduğundan stgdiff herhangi bir fark göstermez. Bu manipülasyonlar yalnızca ikili gösterim incelenerek yakalanamaz.

  • Mevcut bir modülün, daha sonraki bir tarihte uyumsuz yeni bir çekirdek tarafından yüklenmesi KMI ile uyumlu olmadığı kabul edilir. 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 edin

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

Ayrıca, CONFIG_MODVERSIONS etkinleştirilmiş tam çekirdek derlemesi, normal derleme işleminin 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, sembol adı, sembol ad alanı, simgeyi dışa aktaran vmlinux veya modül adı ve dışa aktarma türünden (örneğin, EXPORT_SYMBOL yerine EXPORT_SYMBOL_GPL) oluşur.

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 sembolde CRC değer 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ı giderme

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, aşağıdaki komutta gösterildiği gibi çekirdeği oluşturmak için kullandığınız komutun başına KBUILD_SYMTYPES=1 ekleyerek GKI çekirdeğini ve cihaz çekirdeğinizi 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 simgenin 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. Ö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ü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ı simge için UNKNOWN değerine ve diğer çekirdekteki .symtypes dosyası simge veya veri türünün genişletilmiş görünümüne sahiptir.

Ö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'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. Ü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 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, çekirdeğinizde yapılan ve GKI çekirdeğinde bulunmayan bir değişiklikten kaynaklanıyor.

  5. Değişikliği belirleyin, çekirdekte geri alın veya ACK'ye yükleyip birleştirmesini sağlayın.

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.

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 kodundaki simgenin tanımını bulun (genellikle .h dosyalarında).

    • Çekirdeğiniz ile GKI çekirdeği arasındaki sembol farkları için aşağıdaki komutu çalıştırarak kaydı bulun:
    git blame
    
    • Silinen simgeler için (bir simgenin bir ağaçta silindiği ve diğer ağaçta da silinmesini istediğiniz durumlar) 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. Görünmüyorsa kaydı bulana kadar listeyi gözden geçirin.

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