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:
- Çekirdeği ve onun ABI temsilini oluşturun .
- Derleme ile referans arasındaki ABI farklılıklarını analiz edin .
- ABI gösterimini güncelleyin (gerekirse) .
- 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.
- Özellik değişikliği örneği aosp/1345659'dadır .
- Sembol listesi örneği aosp/1346742'dedir .
- ABI XML değişikliği örneği aosp/1349377'dedir .
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.
Ş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ılanCONFIG
, üretim defconfig vegki_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:
Yama seti için Kod İncelemesi +2 almayı bekleyin.
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:
- Sesin çalışması için aosp/1289677 gereklidir.
- USB'nin çalışması için aosp/1295945 gereklidir.
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:
- aosp/1250412 termal bir özellik değişikliğidir.
- aosp/1288857 bir
EXPORT_SYMBOL_GPL
değişikliğidir.
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ızcatask_struct
vemm_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ı zamandamm_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 çekirdeklerineCONFIG_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 zamanstruct device
fwnode
alanı artık o modül için opak değildir. Modül daha sonradevice->fwnode->dev
veyadevice->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. Üstelikstgdiff
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:
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'tekiKBUILD_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.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);
.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 * )
İ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:
Bu farklılığa sahip simge veya veri tipini tanımlayan başlık dosyasını açın. Örneğin,
struct fwnode_handle
içininclude/linux/fwnode.h
dosyasını düzenleyin.Başlık dosyasının en üstüne aşağıdaki kodu ekleyin:
#ifdef CRC_CATCH #error "Included from here" #endif
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
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.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:
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>
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.
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 .