Android Çekirdeği ABI İzleme

Android çekirdeklerinin çekirdek içi ABI'sini stabilize etmek için Android 11 ve sonraki sürümlerde bulunan uygulama İkili Arayüz (ABI) İzleme araçlarını kullanabilirsiniz. Araç, mevcut çekirdek ikili dosyalarından ( vmlinux + GKI modülleri) ABI temsillerini toplar ve karşılaştırır. Bu ABI temsilleri .stg dosyaları ve sembol listeleridir. Gösterimin görünüm verdiği arayüze Çekirdek Modül Arayüzü (KMI) adı verilir. KMI'daki değişiklikleri izlemek ve azaltmak için araçları kullanabilirsiniz.

ABI izleme aracı, AOSP'de geliştirilmiştir ve temsilleri 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çlar, ABI temsillerini toplama ve analiz etme süreci ve bu tür temsillerin çekirdek içi ABI'ye kararlılık sağlamak için kullanımı açıklanmaktadır. Bu sayfa aynı zamanda Android çekirdeklerine yapılacak değişikliklere katkıda bulunmak için bilgi sağlar.

İşlem

Çekirdeğin ABI'sini analiz etmek, çoğu otomatikleştirilebilen birden fazla adım gerektirir:

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

Aşağıdaki talimatlar, desteklenen bir araç zincirini (önceden oluşturulmuş Clang araç zinciri gibi) kullanarak oluşturabileceğiniz herhangi bir çekirdek için işe yarar. repo manifests tüm Android ortak çekirdek dalları ve cihaza özgü çeşitli çekirdekler için mevcuttur; analiz için bir çekirdek dağıtımı oluşturduğunuzda doğru araç zincirinin kullanılmasını sağlarlar.

Sembol listeleri

KMI, çekirdekteki tüm sembolleri ve hatta 30.000'den fazla dışa aktarılan sembolün tamamını içermez. Bunun yerine, satıcı modülleri tarafından kullanılabilecek semboller, çekirdek ağacının kökünde halka açık olarak tutulan bir dizi sembol listesi dosyasında açıkça listelenir. Tüm sembol listesi dosyalarındaki tüm sembollerin birleşimi, kararlı olarak tutulan KMI sembolleri kümesini tanımlar. Örnek bir sembol listesi dosyası abi_gki_aarch64_db845c'dir ve DragonBoard 845c için gerekli sembolleri bildirir.

Yalnızca bir sembol listesinde listelenen semboller ve bunların ilgili yapıları ve tanımları KMI'nın parçası olarak kabul edilir. İhtiyacınız olan semboller mevcut değilse değişiklikleri sembol listelerinize gönderebilirsiniz. Yeni arayüzler bir sembol listesine eklendikten ve KMI açıklamasının bir parçası olduktan sonra, kararlı olarak korunurlar ve dal dondurulduktan sonra sembol listesinden kaldırılmamalı veya değiştirilmemelidir.

Her Android Ortak Çekirdek (ACK) KMI çekirdek dalının kendi simge listeleri kümesi vardır. Farklı KMI çekirdek dalları arasında ABI stabilitesini sağlamaya yönelik hiçbir girişimde bulunulmamaktadır. Örneğin, android12-5.10 için KMI, android13-5.10 için KMI'dan tamamen bağımsızdır.

ABI araçları, kararlılık açısından hangi arayüzlerin izlenmesi gerektiğini sınırlamak için KMI sembol listelerini kullanır. Ana sembol listesi, GKI çekirdek modüllerinin gerektirdiği sembolleri içerir. Satıcıların, güvendikleri arayüzlerin ABI uyumluluğunu sürdürmesini sağlamak için ek sembol listeleri göndermeleri ve güncellemeleri bekleniyor. Örneğin, android13-5.15 yönelik sembol listelerinin listesini görmek için https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android adresine bakın.

Sembol listesi, belirli satıcı veya cihaz için gerekli olduğu bildirilen sembolleri 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 geçmiş veri yapıları da dahil olmak üzere her sembolün ayrıntılarını belirler.

KMI dondurulduğunda mevcut KMI arayüzlerinde hiçbir değişikliğe izin verilmez; istikrarlılar. Ancak satıcılar, eklemeler mevcut ABI'nin kararlılığını etkilemediği sürece KMI'ya sembol eklemekte özgürdür. Yeni eklenen semboller, bir KMI sembol listesi tarafından alıntılandıkları anda stabil kalırlar. Hiçbir aygıtın bu sembole bağımlı olarak gönderilmediği doğrulanmadığı sürece, semboller bir çekirdeğe ait listeden kaldırılmamalıdır.

Sembol listeleriyle nasıl çalışılır bölümündeki talimatları kullanarak bir cihaz için KMI sembol listesi oluşturabilirsiniz. Birçok ortak, ACK başına bir sembol listesi sunar ancak bu zor bir gereklilik değildir. Bakım konusunda yardımcı olması halinde birden fazla sembol listesi gönderebilirsiniz.

KMI'yi genişletin

KMI sembolleri ve ilgili yapılar kararlı olarak korunurken (yani donmuş bir KMI'ya sahip bir çekirdekteki kararlı arayüzleri bozan değişiklikler kabul edilemez) GKI çekirdeği uzantılara açık kalır, böylece yılın ilerleyen dönemlerinde gönderilen cihazların tümünü tanımlamasına gerek kalmaz. KMI donmadan önceki bağımlılıkları. KMI'yi genişletmek için, KMI donmuş olsa bile yeni veya mevcut dışa aktarılan çekirdek işlevleri için KMI'ya yeni semboller ekleyebilirsiniz. KMI'yi bozmadıkları takdirde yeni çekirdek yamaları da kabul edilebilir.

KMI kırılmaları hakkında

Bir çekirdeğin kaynakları vardır ve ikili dosyalar bu kaynaklardan oluşturulur. ABI tarafından izlenen çekirdek dalları, mevcut GKI ABI'nin ( .stg dosyası biçiminde) bir ABI temsilini içerir. İkili dosyalar ( vmlinux , Image ve herhangi bir GKI modülü) oluşturulduktan sonra ikili dosyalardan bir ABI temsili çıkarılabilir. Çekirdek kaynak dosyasında yapılan herhangi bir değişiklik ikili dosyaları etkileyebilir ve dolayısıyla çıkarılan .stg dosyasını da etkileyebilir. AbiAnalyzer analizörü, taahhüt edilen .stg dosyasını yapı yapılarından çıkarılan dosyayla karşılaştırır ve anlamsal bir fark bulursa Gerrit'teki değişikliğe bir Lint-1 etiketi koyar.

ABI kırılmalarını ele alın

Örnek olarak aşağıdaki yama çok bariz bir ABI kırılmasını ortaya koyuyor:

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 yama uygulanmış halde build ABI'yi çalıştırdığınızda, araç sıfırdan farklı bir hata koduyla çıkar ve buna 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 tespit edilen ABI farklılıkları

Hataların en yaygın nedeni, sürücünün çekirdekten gelen ve sembol listelerinin hiçbirinde yer almayan yeni bir sembolü kullanmasıdır.

Sembol, sembol listesine ( android/abi_gki_aarch64 ) dahil değilse, önce EXPORT_SYMBOL_GPL( symbol_name ) ile dışa aktarıldığını doğrulamanız ve ardından ABI XML gösterimini ve sembol listesini güncellemeniz gerekir. Örneğin, aşağıdaki değişiklikler, sembol listesinin ve ABI XML gösteriminin güncellenmesini içeren yeni Artımlı FS özelliğini android-12-5.10 dalına ekler.

Sembol dışa aktarıldıysa (sizin tarafınızdan veya daha önce dışa aktarılmışsa) ancak başka hiçbir sürücü onu kullanmıyorsa, aşağıdakine benzer bir yapı 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ğinizdeki hem de ACK'daki KMI sembol listesini güncelleyin (bkz . ABI gösterimini güncelleme ). ACK'deki ABI XML ve sembol listesini güncelleme örneği için aosp/1367601 adresine bakın.

Çekirdek ABI arızalarını giderin

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

ABI Kırılma Akış Şeması

Şekil 1. ABI kırılma çözümü

ABI değişikliklerinden kaçınmak için kodu yeniden düzenleyin

Mevcut ABI'yi değiştirmekten kaçınmak için her türlü çabayı gösterin. Çoğu durumda ABI'yi etkileyen değişiklikleri kaldırmak için kodunuzu yeniden düzenleyebilirsiniz.

  • Yapı alanı değişiklikleri yeniden düzenleniyor. Bir değişiklik, bir hata ayıklama özelliği için ABI'yi değiştirirse, alanların çevresine (yapılarda ve kaynak referanslarında) bir #ifdef ekleyin ve #ifdef için kullanılan CONFIG , üretim defconfig ve gki_defconfig için devre dışı bırakıldığından emin olun. ABI'yi bozmadan bir yapıya hata ayıklama yapılandırmasının nasıl eklenebileceğine dair bir örnek için bu yama setine bakın.

  • Çekirdek çekirdeği değiştirmemek için özelliklerin yeniden düzenlenmesi. Ortak modülleri desteklemek için ACK'ya yeni özelliklerin eklenmesi gerekiyorsa, çekirdek ABI'yi değiştirmekten kaçınmak için değişikliğin ABI bölümünü yeniden düzenlemeyi deneyin. Çekirdek ABI'sini değiştirmeden ek işlevsellik eklemek amacıyla mevcut ABI çekirdeğini kullanma örneği için aosp/1312213 adresine bakın.

Android Gerrit'te bozuk bir ABI'yi düzeltin

ABI çekirdeğini kasıtlı olarak bozmadıysanız, ABI izleme aracının sağladığı rehberliği kullanarak araştırma yapmanız gerekir. Arızaların en yaygın nedenleri, değişen veri yapıları ve ilgili sembol CRC değişiklikleri veya yukarıda belirtilenlerden 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, bkz . Çekirdeği ve onun ABI gösterimini oluşturma .

Lint-1 etiketleri hakkında

Değişiklikleri dondurulmuş veya kesinleştirilmiş bir KMI içeren bir şubeye yüklerseniz, değişikliklerin kararlı ABI'yi uyumsuz bir şekilde etkilemediğinden emin olmak için değişikliklerin AbiAnalyzer geçmesi gerekir. Bu işlem sırasında AbiAnalyzer , derleme sırasında oluşturulan ABI raporunu arar (normal derlemeyi gerçekleştiren genişletilmiş bir yapı ve ardından bazı ABI çıkarma ve karşılaştırma adımları).

AbiAnalyzer boş olmayan bir rapor bulursa Lint-1 etiketini ayarlar ve değişikliğin gönderilmesi çözümlenene kadar engellenir; yama seti bir Lint+1 etiketi alana kadar.

Çekirdek ABI'yi güncelleyin

ABI'yi değiştirmek kaçınılmazsa kod değişikliklerinizi, ABI gösterimini ve sembol 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ı izleyin:

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

  2. Yama seti için Kod İncelemesi +2 almayı bekleyin.

  3. Referans ABI gösterimini 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ükleyin

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 göre seçilebilir. Örneğin:

  • Bir ABI değişikliği ACK ile paylaşılabilecek bir özellik içinse, bu değişiklik olduğu gibi ACK'ya isteğe göre seçilebilir. Örneğin, aşağıdaki değişikliklerin CTS veya VTS testi için gerekli olmadığı ancak ACK ile paylaşılmasında sakınca yoktur:

  • Bir ABI değişikliği, ACK'ye dahil edilmesi gerekmeyen yeni bir özellik getiriyorsa, aşağıdaki bölümde açıklandığı gibi bir saplama kullanarak sembolleri ACK'ye tanıtabilirsiniz.

ACK için taslakları kullanın

Saplamalar yalnızca performans ve güç değişiklikleri gibi ACK'ye fayda sağlamayan çekirdek çekirdek değişiklikleri için gerekli olmalıdır. Aşağıdaki listede, GKI için ACK'daki taslak ve kısmi isteğe bağlı seçim örneklerinin ayrıntıları verilmektedir.

  • Çekirdek izolasyon özelliği saplaması ( aosp/1284493 ). ACK'deki işlevsellik gerekli değildir, ancak modüllerinizin bu sembolleri kullanabilmesi için sembollerin ACK'da mevcut olması gerekir.

  • Satıcı modülü için yer tutucu sembolü ( aosp/1288860 ).

  • İşlem başına mm olay izleme özelliğinin yalnızca ABI'ye özel seçilmiş özelliği ( aosp/1288454 ). Orijinal yama, ACK olarak özenle seçilmiş ve daha sonra, yalnızca task_struct ve mm_event_count için ABI farkını çözmek için gerekli değişiklikleri içerecek şekilde kırpılmıştır. Bu yama aynı zamanda mm_event_type numaralandırmasını da son üyeleri içerecek şekilde günceller.

  • Yeni ABI alanlarının eklenmesinden daha fazlasını gerektiren, termal yapıdaki ABI değişikliklerinin kısmi seçimi.

    • 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, birden fazla termal bölgeyi tek bir sensöre kaydetmek için sensör parametre yapısını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 olmadığından emin olarak iş ortaklarının üretim çekirdeklerine CONFIG_NL80211_TESTMODE eklemelerine ve yine de GKI uyumluluğunu sürdürmelerine olanak tanıdı.

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

GKI çekirdekleri, dışa aktarılan simgeleri ( EXPORT_SYMBOL_GPL() kullanılarak dışa aktarılan simgeler gibi) bir simge 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 bir 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, sembol kırpmayı içermeyen bir GKI çekirdek yapısı kullanabilirsiniz (bu, genellikle dışa aktarılan tüm sembollerin kullanılabileceği anlamına gelir). Bu yapıları bulmak için ci.android.com adresinde kernel_debug_aarch64 yapılarını arayın.

Modül sürümlendirmeyi kullanarak KMI'yı zorunlu kılın

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üm oluşturmayı ( CONFIG_MODVERSIONS ) kullanır. Modül sürüm oluşturma, bir modülün beklenen KMI'sının vmlinux KMI ile eşleşmemesi durumunda modül yükleme sırasında döngüsel artıklık denetimi (CRC) uyumsuzluk hatalarına neden olabilir. Örneğin, module_layout() sembolüne ilişkin CRC uyumsuzluğu nedeniyle modül yükleme sırasında meydana gelen tipik bir hata aşağıdadı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 versiyonlamanın kullanım alanları

Modül versiyonlama aşağıdaki nedenlerden dolayı faydalıdır:

  • Modül versiyonlama, 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 gelecekte yapılacak değişikliklerden sonra bozulurlar.

    Örnek olarak struct device fwnode alanını düşünün. device->fw_node alanlarında değişiklik yapamamaları veya boyutu hakkında varsayımlarda bulunamamaları için bu alanın modüllere karşı şeffaf olması ZORUNLUDUR.

    Bununla birlikte, eğer bir modül <linux/fwnode.h> içeriyorsa (doğrudan veya dolaylı olarak), o zaman struct device fwnode alanı artık o modül için opak değildir. Modül daha sonra device->fwnode->dev veya device->fwnode->ops değişiklik yapabilir. Bu senaryo, aşağıda belirtilen çeşitli nedenlerden dolayı sorunludur:

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

    • Gelecekteki bir çekirdek güncellemesi struct fwnode_handle ( fwnode veri türü) değiştirirse, modül artık yeni çekirdekle çalışmaz. Üstelik stgdiff herhangi bir farklılık göstermez çünkü modül, dahili veri yapılarını yalnızca ikili temsili inceleyerek yakalanamayacak şekilde doğrudan değiştirerek KMI'yı kırıyor.

  • Geçerli bir modül, daha sonraki bir tarihte uyumlu olmayan yeni bir çekirdek tarafından yüklendiğinde KMI ile uyumlu olmadığı kabul edilir. Modül sürüm oluşturma, çekirdekle KMI uyumlu olmayan bir modülün yanlışlıkla yüklenmesini önlemek için bir çalışma zamanı kontrolü ekler. Bu kontrol, hata ayıklaması zor çalışma zamanı sorunlarını ve KMI'da tespit edilemeyen bir uyumsuzluktan kaynaklanabilecek çekirdek çökmelerini önler.

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

Cihazı başlatmadan CRC uyumsuzluklarını kontrol edin

stgdiff diğer ABI farklılıklarıyla birlikte çekirdekler arasındaki CRC uyumsuzluklarını karşılaştırır ve raporlar.

Ayrıca, CONFIG_MODVERSIONS etkinleştirilmiş tam çekirdek yapısı, normal oluşturma 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 sembol için bir satır bulunur. Her satır, CRC değeri, sembol adı, sembol ad alanı, sembolü dışa aktaran vmlinux veya modül adı ve dışa aktarma türünden oluşur (örneğin, EXPORT_SYMBOL ve EXPORT_SYMBOL_GPL ).

vmlinux tarafından dışa aktarılan sembollerdeki CRC farklılıklarını kontrol etmek için Module.symvers dosyalarını GKI yapısı ile derlemeniz arasında karşılaştırabilirsiniz. vmlinux tarafından dışa aktarılan herhangi bir sembolde CRC değeri farkı varsa ve o sembol cihazınıza yüklediğiniz modüllerden biri tarafından kullanılıyorsa modül yüklenmez.

Tüm yapı yapılarına sahip değilseniz ancak GKI çekirdeğinin ve çekirdeğinizin vmlinux dosyalarına sahipseniz, aşağıdaki komutu her iki çekirdekte çalıştırarak ve çıktıyı 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ü için CRC değerini kontrol eder:

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

CRC uyumsuzluklarını çözme

Bir modül yüklerken CRC uyumsuzluğunu çözmek için aşağıdaki adımları kullanın:

  1. Aşağıdaki komutta gösterildiği gibi --kbuild_symtypes seçeneğini kullanarak GKI çekirdeğini ve aygıtınızın çekirdeğini 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 bakın.

    Android 13 ve daha düşük sürümler için, aşağıdaki komutta gösterildiği gibi, çekirdeği oluşturmak için kullandığınız komutun KBUILD_SYMTYPES=1 değerini ekleyerek GKI çekirdeğini ve cihazınızın çekirdeğini oluşturun:

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

    build_abi.sh, KBUILD_SYMTYPES=1 bayrağı örtülü olarak zaten ayarlanmıştır.

  2. Aşağıdaki komutu kullanarak, CRC uyumsuzluğuna sahip 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ı, GKI'da karşılık gelen bir .symtypes dosyasına ve cihazınızın çekirdek yapısı yapılarına sahiptir. 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 formatı sembol başına bir (potansiyel olarak çok uzun) satırdır.

    • Satırın başındaki [s|u|e|etc]# sembolün [struct|union|enum|etc] veri türünde olduğu anlamına gelir. Örneğin:

      t#bool typedef _Bool bool
      
    • Satırın başındaki eksik # öneki, sembolün bir fonksiyon olduğunu gösterir. Örneğin:

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

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

Bir çekirdek bir sembolü veya veri tipini modüller için opak tutuyorsa ve diğer çekirdek tutmuyorsa, bu fark iki çekirdeğin .symtypes dosyaları arasında ortaya çıkar. Çekirdeklerden birindeki .symtypes dosyasında bir sembol UNKNOWN ve diğer çekirdekteki .symtypes dosyasında sembol veya veri türünün genişletilmiş görünümü bulunur.

Örneğin, çekirdeğinizdeki include/linux/device.h dosyasına aşağıdaki satırı eklemek CRC uyumsuzluklarına neden olur; bunlardan biri module_layout() içindir:

 #include <linux/fwnode.h>

Bu sembol için module.symtypes karşılaştırıldığında aşağıdaki farklılıklar ortaya çıkar:

 $ 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 UNKNOWN bir değeri varsa ve GKI çekirdeği, sembolün genişletilmiş görünümüne sahipse (çok düşük bir ihtimal), en son GKI çekirdek tabanını kullanabilmeniz için en son Android Common Kernel'i ç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ına sahiptir. Bunun nedeni, çekirdeğinizdeki dosyalardan birinin, GKI çekirdeğinde bulunmayan bir #include eklemesidir.

Çoğu zaman düzeltme, yeni #include öğesini genksyms gizlemek kadar basittir.

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

Aksi takdirde, farka neden olan #include include'ı belirlemek için şu adımları izleyin:

  1. Bu farklılığa sahip simge veya veri tipini tanımlayan başlık dosyasını açın. Örneğin, struct fwnode_handle için include/linux/fwnode.h dosyasını 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. CRC uyumsuzluğu olan modülün .c dosyasında, #include satırlarından herhangi birinin öncesine ilk satır olarak aşağıdakini ekleyin.

    #define CRC_CATCH 1
    
  4. Modülünüzü derleyin. Ortaya çıkan derleme zamanı hatası, bu CRC uyumsuzluğuna yol açan #include başlık dosyası zincirini gösterir. Örneğin:

    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 eksik olan bir değişiklikten kaynaklanmaktadır.

  5. Değişikliği tanımlayın, çekirdeğinize geri alın veya ACK'ya yükleyin ve birleştirilmesini sağlayın .

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

Bir sembol veya veri türü için CRC uyumsuzluğu görünürlükteki bir farklılıktan kaynaklanmıyorsa, bu durum veri türünün kendisindeki gerçek değişikliklerden (eklemeler, çıkarmalar veya değişiklikler) kaynaklanmaktadır.

Örneğin, çekirdeğinizde aşağıdaki değişikliği yapmak, birçok sembolün bu tür bir değişiklikten dolaylı olarak etkilenmesi nedeniyle birçok CRC uyumsuzluğuna 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 uyumsuzluğu devm_of_platform_populate() içindir.

Bu sembol için .symtypes dosyalarını karşılaştırırsanız şöyle 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ü tanımlamak için şu adımları izleyin:

  1. Sembolün tanımını kaynak kodunda bulun (genellikle .h dosyalarında).

    • Çekirdeğiniz ile GKI çekirdeği arasındaki basit sembol farkları için aşağıdaki komutu çalıştırarak taahhüdü bulun:
    git blame
    
    • Silinen semboller için (bir sembolün bir ağaçta silindiği ve onu diğer ağaçta da silmek istediğiniz durumlarda), 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ütler listesini inceleyin. İlk taahhüt muhtemelen aradığınız şeydir. Değilse, taahhüdü bulana kadar listeyi gözden geçirin.

  3. Değişikliği tanımladıktan sonra, ya çekirdeğinizde onu geri alın ya da ACK'ya yükleyip birleştirilmesine izin verin .