ऐप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) मॉनिटरिंग टूल का इस्तेमाल किया जा सकता है. यह टूल इनमें उपलब्ध है
Android 11 और उसके बाद के वर्शन, इन-कर्नेल को स्थिर रखने के लिए
Android कर्नेल का एबीआई. टूल, मौजूदा कर्नेल बाइनरी (vmlinux
+ GKI मॉड्यूल) से एबीआई के रिप्रज़ेंटेशन इकट्ठा करता है और उनकी तुलना करता है. एबीआई के ये प्रतिनिधित्व, .stg
फ़ाइलें और सिंबल की सूचियां हैं. इंटरफ़ेस
जो प्रज़ेंटेशन से एक व्यू मिलता है उसे केर्नेल मॉड्यूल इंटरफ़ेस कहा जाता है
(केएमआई). KMI में होने वाले बदलावों को ट्रैक करने और उन्हें कम करने के लिए, टूल का इस्तेमाल किया जा सकता है.
यह एबीआई मॉनिटरिंग टूल
एओएसपी में बनाया गया
और इस्तेमाल
एसटीजी (या
libabigail
इंच
Android 13 और उससे पहले वाले वर्शन के लिए)
प्रतिनिधित्व.
इस पेज पर, टूल के बारे में बताया गया है. साथ ही, एबीआई के रिप्रज़ेंटेशन को इकट्ठा करने और उनका विश्लेषण करने की प्रोसेस के बारे में भी बताया गया है. इसके अलावा, इन-कर्नल एबीआई को स्थिरता देने के लिए, ऐसे रिप्रज़ेंटेशन के इस्तेमाल के बारे में भी बताया गया है. इस पेज पर, Android के कर्नेल में बदलाव करने के बारे में भी जानकारी दी गई है.
प्रोसेस
कर्नेल के एबीआई का विश्लेषण कई चरणों में होता है, जिनमें से ज़्यादातर चरण अपने-आप होते हैं:
- कर्नल और उसके एबीआई का प्रतिनिधित्व बनाएं.
- बिल्ड और रेफ़रंस के बीच एबीआई के अंतर का विश्लेषण करें.
- एबीआई का प्रतिनिधित्व अपडेट करें (अगर ज़रूरी हो).
- सिंबल वाली सूचियों के साथ काम करें.
नीचे दिए गए निर्देश किसी भी
कर्नेल का इस्तेमाल करें जिसे
इस्तेमाल किए जा सकने वाले टूलचेन (जैसे कि पहले से बने Clang टूलचेन). repo manifests
Android के सभी कॉमन कर्नेल ब्रांचों और कई
खास तौर पर किसी डिवाइस के लिए तैयार की गई हैं. ये पक्का करती हैं कि सही टूलचेन का इस्तेमाल तब किया जाए, जब
विश्लेषण के लिए एक कर्नेल डिस्ट्रिब्यूशन बनाएं.
सिंबल की सूचियां
KMI में, कर्नेल के सभी सिंबल या एक्सपोर्ट किए गए 30,000 से ज़्यादा सिंबल शामिल नहीं होते. इसके बजाय, वेंडर मॉड्यूल के ज़रिए इस्तेमाल किए जा सकने वाले सिंबल, सिंबल की सूची वाली फ़ाइलों के सेट में साफ़ तौर पर शामिल किए जाते हैं. इन फ़ाइलों को कर्नेल ट्री के रूट में सार्वजनिक तौर पर रखा जाता है. सभी सिंबल की सूची वाली फ़ाइलों में मौजूद सभी सिंबल का यूनियन, स्थिर के तौर पर बनाए गए केएमआई सिंबल के सेट को तय करता है. सिंबल की सूची वाली फ़ाइल का उदाहरण, abi_gki_aarch64_db845c है. इसमें DragonBoard 845c के लिए ज़रूरी सिंबल की जानकारी दी गई है.
केवल किसी प्रतीक सूची में सूचीबद्ध प्रतीक और उनसे संबंधित संरचना और परिभाषाओं को केएमआई का हिस्सा माना जाता है. आप अपनी चिह्न सूची जोड़ देता है. नए इंटरफ़ेस के आने के बाद इनमें सिंबल की सूची शामिल होती है और ये KMI की जानकारी का हिस्सा होते हैं. साथ ही, उन्हें हमेशा के लिए बनाए रखा जाता है और इसे प्रतीक सूची से निकाला या संशोधित नहीं किया जाना चाहिए फ़्रीज़ किया गया.
हर Android Common Kernel (ACK) KMI कर्नेल ब्रांच में, सिंबल का अपना सेट होता है
सूचियां. अलग-अलग KMI कर्नेल के बीच एबीआई स्थिरता देने की कोई कोशिश नहीं की गई है
शाखाएं. उदाहरण के लिए, android12-5.10
के लिए केएमआई, android13-5.10
के लिए केएमआई से पूरी तरह से अलग होता है.
ABI टूल, KMI सिंबल की सूचियों का इस्तेमाल करके यह तय करते हैं कि किन इंटरफ़ेस को स्थिरता के लिए मॉनिटर किया जाना चाहिए. मुख्य सिंबल की सूची में वे सिंबल होते हैं जो GKI के kernel मॉड्यूल के लिए ज़रूरी होते हैं. वेंडर को अन्य सिंबल की सूचियां सबमिट और अपडेट करनी होंगी, ताकि यह पक्का किया जा सके कि वे इंटरफ़ेस जिन पर वे भरोसा करते हैं वे एबीआई के साथ काम करते रहें. उदाहरण के लिए, अगर आपको
के लिए प्रतीक सूचियों का android13-5.15
, इसे देखें
https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android
सिंबल की सूची में वे सिंबल होते हैं जो किसी खास इवेंट के लिए ज़रूरी होते हैं विक्रेता या डिवाइस. टूल में इस्तेमाल की जाने वाली पूरी सूची, सभी के यूनियन की होती है केएमआई सिंबल की सूची वाली फ़ाइलें. एबीआई टूल, हर सिंबल की जानकारी तय करते हैं. इसमें फ़ंक्शन हस्ताक्षर और नेस्ट किए गए डेटा स्ट्रक्चर भी शामिल हैं.
KMI फ़्रीज़ होने पर, मौजूदा KMI इंटरफ़ेस में कोई बदलाव नहीं किया जा सकता. ये इंटरफ़ेस स्थिर होते हैं. हालांकि, वेंडर किसी भी समय केएमआई में सिंबल जोड़ सकते हैं जब तक कि जोड़े जाने से मौजूदा एबीआई की स्थिरता पर कोई असर नहीं पड़ता. जोड़े गए नए चिह्नों को, KMI के चिह्न की सूची में शामिल करने के बाद, स्थिर माना जाता है. कर्नेल के लिए सूची से सिंबल तब तक नहीं हटाए जाने चाहिए, जब तक उनकी पुष्टि नहीं की जाती कि किसी भी डिवाइस ने उस सिंबल पर निर्भरता के साथ कभी भी शिपिंग नहीं की है.
यहां दिए गए निर्देशों का पालन करके, किसी डिवाइस के लिए KMI के सिंबल की सूची जनरेट की जा सकती है सिंबल वाली सूचियों के साथ काम करने का तरीका. कई पार्टनर, ACK के हिसाब से एक सिंबल की सूची सबमिट करते हैं. हालांकि, ऐसा करना ज़रूरी नहीं है. अगर इससे रखरखाव में मदद मिलती है, तो एक से ज़्यादा सिंबल की सूचियां सबमिट की जा सकती हैं.
केएमआई को बढ़ाएं
केएमआई सिंबल और उनसे जुड़े स्ट्रक्चर को स्थायी तौर पर बनाए रखा जाता है (मतलब, ऐसे बदलाव जो फ़्रीज़ किए गए KMI के साथ कर्नेल में स्थिर इंटरफ़ेस को तोड़ते हैं स्वीकार किए जाते हैं) जीकेआई कर्नेल एक्सटेंशन के लिए खुला रहता है, ताकि डिवाइस शिपिंग कर सकें उन्हें यह तय करने की ज़रूरत नहीं है कि साल के आखिर में फ़्रीज़ किया गया. केएमआई की सीमा बढ़ाने के लिए, केएमआई में नए सिंबल जोड़े जा सकते हैं एक्सपोर्ट किए गए मौजूदा कर्नेल फ़ंक्शन, भले ही केएमआई फ़्रीज़ हो. नया कर्नेल अगर पैच केएमआई का उल्लंघन नहीं करते, तो उन्हें भी स्वीकार किया जा सकता है.
केएमआई की गड़बड़ी के बारे में जानकारी
किसी कर्नेल में सोर्स होते हैं और बाइनरी उन सोर्स से बनाई जाती हैं.
एबीआई की निगरानी वाली कर्नेल शाखाओं में, मौजूदा GKI एबीआई (.stg
फ़ाइल के तौर पर) का एबीआई दिखाया जाता है. बाइनरी (vmlinux
, Image
, और GKI के सभी मॉड्यूल) बनने के बाद, बाइनरी से एबीआई का प्रतिनिधित्व निकाला जा सकता है. किसी भी कर्नेल सोर्स फ़ाइल में किए गए बदलाव से, बाइनरी पर असर पड़ सकता है. साथ ही, इससे निकाले गए .stg
पर भी असर पड़ सकता है. AbiAnalyzer
ऐनालाइज़र
बनाई गई आर्टफ़ैक्ट से निकाली गई फ़ाइल के साथ तय .stg
फ़ाइल और
अगर मुझे सिमैंटिक अंतर मिलता है, तो Gerrit में बदलाव पर लिंट-1 लेबल होगा.
एबीआई की गड़बड़ियों को मैनेज करना
उदाहरण के लिए, नीचे दिए गए पैच में एबीआई (ऑब्जेक्ट फ़ाइल फ़ॉर्मैट) में बहुत साफ़ तौर पर बदलाव किया गया है:
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.
इस पैच को लागू करके एबीआई बनाने पर, टूल इस पैच के साथ बंद हो जाता है एक नॉन-ज़ीरो गड़बड़ी कोड और इस तरह के एबीआई अंतर की रिपोर्ट करता है:
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
बिल्ड के समय एबीआई में अंतर का पता चलना
गड़बड़ियों की सबसे सामान्य वजह यह है कि ड्राइवर किसी कर्नेल के लिए सेट है, जो किसी भी प्रतीक सूची में नहीं है.
अगर सिंबल, सिंबल की सूची (android/abi_gki_aarch64
) में शामिल नहीं है, तो आपको पहले पुष्टि करनी होगी कि इसे EXPORT_SYMBOL_GPL(symbol_name)
के साथ एक्सपोर्ट किया गया है. इसके बाद, एबीआई एक्सएमएल के तौर पर दिखाए जाने वाले डेटा और सिंबल की सूची को अपडेट करें. उदाहरण के लिए, इन बदलावों से android-12-5.10
शाखा में इंक्रीमेंटल एफ़एस की नई सुविधा जुड़ती है. इसमें, सिंबल की सूची और एबीआई एक्सएमएल का अपडेट शामिल है.
- सुविधा में बदलाव का उदाहरण aosp/1345659 पर टैप करें.
- प्रतीक सूची का उदाहरण इसमें है aosp/1346742 पर टैप करें.
- एबीआई एक्सएमएल में बदलाव का उदाहरण यहां दिया गया है aosp/1349377 पर टैप करें.
अगर सिंबल को एक्सपोर्ट किया गया है (आपने या उसे पहले एक्सपोर्ट किया था) लेकिन नहीं कोई अन्य ड्राइवर इसका इस्तेमाल कर रहा है, तो आपको नीचे बताई गई गड़बड़ी से मिलती-जुलती बिल्ड गड़बड़ी मिल सकती है.
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
रिज़ॉल्व करने के लिए, अपने कर्नेल और ACK, दोनों में KMI सिंबल की सूची अपडेट करें (देखें एबीआई की जानकारी अपडेट करना). ACK में ABI एक्सएमएल और सिंबल की सूची को अपडेट करने के उदाहरण के लिए, aosp/1367601 देखें.
कर्नेल ABI ब्रेकेज का समाधान करें
कोड को फिर से लिखकर, एबीआई में बदलाव न करने या एबीआई के रिप्रज़ेंटेशन को अपडेट करके, कर्नेल एबीआई के गड़बड़ियों को ठीक किया जा सकता है. इनका इस्तेमाल करें चार्ट देखकर जानें कि आपके लिए सबसे सही तरीका कौनसा है.
पहला डायग्राम. एबीआई के उल्लंघन को ठीक करना
एबीआई में बदलावों से बचने के लिए, कोड को रीफ़ैक्टर करें
मौजूदा एबीआई में बदलाव करने से बचने की पूरी कोशिश करें. कई मामलों में, आपको एबीआई पर असर डालने वाले बदलावों को हटाने के लिए, अपने कोड को रीफ़ैक्टर करें.
स्ट्रक्चर फ़ील्ड में बदलावों को फिर से तैयार करना. अगर किसी बदलाव से डीबग करने की सुविधा के लिए एबीआई में बदलाव होता है, तो फ़ील्ड के आस-पास (स्ट्रक्चर और सोर्स रेफ़रंस में)
#ifdef
जोड़ें. साथ ही, पक्का करें कि#ifdef
के लिए इस्तेमाल किया गयाCONFIG
, प्रोडक्शन defconfig औरgki_defconfig
के लिए बंद हो. एबीआई को बदले बिना, किसी स्ट्रक्चर में डीबग कॉन्फ़िगरेशन जोड़ने का उदाहरण देखने के लिए, इस पैच सेट को देखें.कोर कर्नेल में बदलाव न करने के लिए, सुविधाओं को फिर से तैयार करना. अगर पार्टनर मॉड्यूल के साथ काम करने के लिए, ACK में नई सुविधाएं जोड़नी हैं, तो बदलाव के एबीआई हिस्से को फिर से लिखने की कोशिश करें, ताकि कर्नेल एबीआई में बदलाव न करना पड़े. मौजूदा कर्नेल एबीआई का इस्तेमाल करके, कर्नेल एबीआई में बदलाव किए बिना अतिरिक्त सुविधाएं जोड़ने का उदाहरण देखने के लिए, aosp/1312213 देखें.
Android Gerrit पर काम न करने वाले एबीआई को ठीक करना
अगर आपने जान-बूझकर कर्नेल एबीआई को नहीं तोड़ा है, तो आपको एबीआई मॉनिटरिंग टूल से मिले दिशा-निर्देशों का इस्तेमाल करके, इसकी जांच करनी होगी. आम तौर पर, डेटा स्ट्रक्चर और उससे जुड़े सिंबल सीआरसी में बदलाव होने की वजह से, डेटा फ़ाइलें क्रैक हो जाती हैं. इसके अलावा, कॉन्फ़िगरेशन के विकल्प में बदलाव होने की वजह से भी ऐसा हो सकता है. टूल से मिली समस्याओं को हल करके शुरुआत करें.
एबीआई से जुड़ी समस्याओं को स्थानीय तौर पर दोहराया जा सकता है. इसके लिए, कर्नल और उसके एबीआई का प्रतिनिधित्व बनाएं लेख पढ़ें.
Lint-1 लेबल के बारे में जानकारी
अगर किसी ऐसी शाखा में बदलाव अपलोड किए जाते हैं जिसमें फ़्रीज़ किया गया या फ़ाइनल किया गया केएमआई है, तो बदलावों को AbiAnalyzer
से पास करना होगा. इससे यह पक्का किया जा सकेगा कि बदलावों का, काम करने वाले एबीआई पर गलत तरीके से असर न पड़े. इस प्रोसेस के दौरान, AbiAnalyzer
उस एबीआई रिपोर्ट को खोजता है जो बिल्ड के दौरान बनाई गई है. यह एक ऐसा एक्सटेंडेड बिल्ड है जो सामान्य बिल्ड के बाद, एबीआई को निकालने और तुलना करने के कुछ चरण करता है.
अगर AbiAnalyzer
को कोई ऐसी रिपोर्ट मिलती है जो खाली नहीं है, तो यह Lent-1 लेबल सेट करती है और
बदलाव को सबमिट करने से तब तक ब्लॉक किया गया है, जब तक कि इस समस्या को हल नहीं कर लिया जाता; जब तक पैचसेट को
लिंट+1 लेबल.
कर्नेल एबीआई को अपडेट करना
अगर एबीआई में बदलाव करना ज़रूरी है, तो आपको कोड में किए गए बदलावों, एबीआई के रिप्रज़ेंटेशन, और सिंबल की सूची को ACK में लागू करना होगा. Lint को -1 हटाने और GKI के साथ काम करने की सुविधा को बनाए रखने के लिए, यह तरीका अपनाएं:
पैचसेट के लिए, कोड की समीक्षा +2 स्टेटस मिलने का इंतज़ार करें.
अपने कोड और एबीआई में हुए बदलावों को मर्ज करें.
ACK में ABI कोड में किए गए बदलाव अपलोड करना
ACK ABI को अपडेट किए जाने के तरीके पर निर्भर करता है.
अगर एबीआई में कोई बदलाव किसी ऐसी सुविधा से जुड़ा है जो सीटीएस या वीटीएस टेस्ट पर असर डालता है, तो के लिए आम तौर पर ACK पर ध्यान दिया जा सकता है. जैसे:
- ऑडियो की सुविधा काम करने के लिए, aosp/1289677 की ज़रूरत होती है.
- यूएसबी के काम करने के लिए, aosp/1295945 की ज़रूरत होती है.
अगर एबीआई में कोई बदलाव किसी ऐसी सुविधा के लिए है जिसे ACK के साथ शेयर किया जा सकता है, तो की अपनी ज़रूरतों के हिसाब से बदलाव के लिए, ACK पर ध्यान दिया जा सकता है. उदाहरण के लिए, नीचे दिए गए बदलाव CTS या VTS के लिए ज़रूरी नहीं हैं, लेकिन इन्हें ACK के साथ शेयर किया जा सकता है:
- aosp/1250412 में एक थर्मल फ़ीचर बदलाव आया है.
- एओएसपी/1288857
एक
EXPORT_SYMBOL_GPL
बदलाव है.
अगर एबीआई में किए गए बदलाव से कोई नई सुविधा मिलती है, जिसे ACK में शामिल करने की ज़रूरत नहीं है, तो स्टब का इस्तेमाल करके ACK में सिंबल जोड़े जा सकते हैं. इसके बारे में अगले सेक्शन में बताया गया है.
ACK के लिए स्टब का इस्तेमाल करना
स्टब सिर्फ़ उन मुख्य कर्नेल बदलावों के लिए ज़रूरी होने चाहिए जिनसे ACK, जैसे कि परफ़ॉर्मेंस और पावर में बदलाव. नीचे दी गई सूची में, GKI के लिए ACK में स्टब और कुछ हिस्सों को चुनकर शामिल करने के उदाहरण दिए गए हैं.
कोर-आइसोलेट फ़ीचर स्टब (aosp/1284493). ACK में ये सुविधाएं होना ज़रूरी नहीं है. हालांकि, आपके मॉड्यूल में इन सिंबल का इस्तेमाल करने के लिए, ACK में ये सिंबल मौजूद होने चाहिए.
वेंडर मॉड्यूल के लिए प्लेसहोल्डर सिंबल (aosp/1288860).
हर प्रोसेस के हिसाब से सिर्फ़ एबीआई के लिए चेरी-पिक
mm
इवेंट ट्रैकिंग सुविधा (aosp/1288454). ओरिजनल पैच को स्वीकार करने के लिए चुना गया था. इसके बाद,task_struct
औरmm_event_count
के लिए एबीआई के अंतर को हल करने के लिए, सिर्फ़ ज़रूरी बदलावों को शामिल करने के लिए पैच को छोटा किया गया था. यह पैचmm_event_type
ईनम को भी अपडेट करता है, ताकि इसमें शामिल किया जा सके और पैसे चुका सकते हैं.थर्मल स्ट्रक्चर एबीआई में किए गए कुछ बदलावों को चुना गया है. इन बदलावों के लिए, एबीआई के नए फ़ील्ड जोड़ने के अलावा और भी काम करने पड़े.
पैच aosp/1255544 ने पार्टनर कर्नेल और ACK के बीच एबीआई के अंतर को ठीक किया.
पैच एओएसपी/1291018 पिछले पैच की GKI टेस्टिंग के दौरान मिली गड़बड़ियों को ठीक किया गया. इस गड़बड़ी को ठीक करने के लिए, सेंसर पैरामीटर स्ट्रक्चर को शुरू किया गया, ताकि एक सेंसर में कई थर्मल ज़ोन रजिस्टर किए जा सकें.
एबीआई में
CONFIG_NL80211_TESTMODE
बदलाव (aosp/1344321). इस पैच में, एबीआई के लिए स्ट्रक्चर में ज़रूरी बदलाव किए गए हैं. साथ ही, यह पक्का किया गया है कि अतिरिक्त फ़ील्ड की वजह से फ़ंक्शन में कोई अंतर न आए. इससे पार्टनर, अपने प्रॉडक्शन कर्नेल मेंCONFIG_NL80211_TESTMODE
को शामिल कर पाएंगे और जीकेआई का पालन भी कर पाएंगे.
रनटाइम के दौरान KMI लागू करें
जीकेआई कर्नेल, TRIM_UNUSED_KSYMS=y
और UNUSED_KSYMS_WHITELIST=<union
of all symbol lists>
कॉन्फ़िगरेशन के विकल्पों का इस्तेमाल करते हैं. इससे एक्सपोर्ट किए गए सिंबल सीमित हो जाते हैं
(जैसे कि EXPORT_SYMBOL_GPL()
का इस्तेमाल करके एक्सपोर्ट किए गए चिह्न)
चिह्न सूची. अन्य सभी सिंबल एक्सपोर्ट नहीं किए जाते. साथ ही, ऐसे मॉड्यूल को लोड करने की अनुमति नहीं है जिसमें एक्सपोर्ट नहीं किए गए सिंबल की ज़रूरत होती है. यह पाबंदी, बिल्ड के समय लागू होती है और मौजूद न होने वाली एंट्री को फ़्लैग किया जाता है.
डेवलपमेंट के मकसद से, ऐसे जीकेआई कर्नेल बिल्ड का इस्तेमाल किया जा सकता है जिसमें
सिंबल को ट्रिम करना (इसका मतलब है कि एक्सपोर्ट किए गए सभी सिंबल इस्तेमाल किए जा सकते हैं). इन बिल्ड को ढूंढने के लिए, ci.android.com पर kernel_debug_aarch64
बिल्ड खोजें.
मॉड्यूल वर्शन का इस्तेमाल करके, केएमआई लागू करें
जेनेरिक कर्नेल इमेज (जीकेआई) के कर्नेल, मॉड्यूल वर्शन का इस्तेमाल करते हैं
(CONFIG_MODVERSIONS
) पर,
रनटाइम. मॉड्यूल वर्शनिंग की वजह से, साइक्लिक रिडंडंसी चेक (सीआरसी) की जांच नहीं हो सकती
अगर किसी मॉड्यूल का अनुमानित केएमआई मेल नहीं खाता है, तो मॉड्यूल लोड होने में लगने वाले समय पर गड़बड़ी
vmlinux
कि.मी. उदाहरण के लिए, module_layout()
सिंबल के सीआरसी मैच न होने की वजह से, मॉड्यूल लोड होने के समय आम तौर पर यह गड़बड़ी होती है:
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 ''
मॉड्यूल के वर्शन का इस्तेमाल
मॉड्यूल वर्शनिंग इन वजहों से फ़ायदेमंद है:
मॉड्यूल वर्शनिंग की वजह से, डेटा स्ट्रक्चर की विज़िबिलिटी में बदलाव हो जाता है. अगर मॉड्यूल, ऐसे डेटा स्ट्रक्चर में बदलाव करते हैं जो पारदर्शी नहीं हैं, यानी ऐसे डेटा स्ट्रक्चर जो केएमआई का हिस्सा नहीं हैं, तो स्ट्रक्चर में आने वाले बदलावों के बाद वे काम नहीं करते.
उदाहरण के लिए,
struct device
में मौजूदfwnode
फ़ील्ड को देखें. यह ज़रूरी है कि मॉड्यूल के लिए यह फ़ील्ड ऐपैरेंट न हो, ताकि वेdevice->fw_node
के फ़ील्ड में बदलाव न कर सकें या उसके साइज़ के बारे में अनुमान न लगा सकें.हालांकि, अगर किसी मॉड्यूल में
<linux/fwnode.h>
(सीधे या किसी दूसरे तरीके से) शामिल है, तोstruct device
में मौजूदfwnode
फ़ील्ड अब उसके लिए पारदर्शी नहीं होगा. कॉन्टेंट बनाने मॉड्यूल फिरdevice->fwnode->dev
में बदलाव कर सकता है याdevice->fwnode->ops
. यह स्थिति कई वजहों से मुश्किल है. यहां बताया गया है:यह उन अनुमानों को तोड़ सकता है जिन्हें कोर कर्नेल कोड, अपने अंदरूनी काम के बारे में बना रहा है डेटा स्ट्रक्चर.
अगर आने वाले समय में, किसी कर्नेल अपडेट में
struct fwnode_handle
(fwnode
का डेटा टाइप) में बदलाव होता है, तो मॉड्यूल नए कर्नेल के साथ काम नहीं करेगा. इसके अलावा, मॉड्यूल काम न करने की वजह से,stgdiff
कोई अंतर नहीं दिखाएगा इंटरनल डेटा स्ट्रक्चर के साथ सीधे तौर पर छेड़छाड़ करके केएमआई को डेटा को सिर्फ़ बाइनरी रिप्रज़ेंटेशन की जांच करके कैप्चर किया जा सकता है.
किसी मौजूदा मॉड्यूल को KMI के साथ काम न करने वाला माना जाता है, जब उसे बाद में किसी ऐसे नए कर्नेल से लोड किया जाता है जो काम नहीं करता. मॉड्यूल वर्शनिंग, रन-टाइम चेक जोड़ता है गलती से ऐसे मॉड्यूल को लोड होने से बचाएं जो कर्नेल के साथ KMI के साथ काम न करता हो. इस जांच से, रनटाइम की उन समस्याओं और कर्नेल क्रैश से बचा जा सकता है जिन्हें डीबग करना मुश्किल होता है. ये समस्याएं, KMI में किसी ऐसे कॉम्पोनेंट के इस्तेमाल से हो सकती हैं जिसकी जानकारी नहीं है.
मॉड्यूल वर्शनिंग चालू करने से, इन सभी समस्याओं से बचा जा सकता है.
डिवाइस को बूट किए बिना सीआरसी मेल न खाने की जांच करना
stgdiff
अन्य के साथ कर्नेल के बीच CRC बेमेल की तुलना और रिपोर्ट करता है
एबीआई में अंतर.
इसके अलावा, CONFIG_MODVERSIONS
सक्षम के साथ एक पूरा कर्नेल बिल्ड जनरेट करता है
Module.symvers
फ़ाइल का इस्तेमाल किया जा सकता है. इस फ़ाइल में, कर्नेल (vmlinux
) और मॉड्यूल से एक्सपोर्ट किए गए हर सिंबल के लिए एक लाइन होती है. हर
लाइन में सीआरसी वैल्यू, सिंबल का नाम, सिंबल का नेमस्पेस, vmlinux
या
सिंबल को एक्सपोर्ट करने वाले मॉड्यूल का नाम और एक्सपोर्ट टाइप (उदाहरण के लिए,
EXPORT_SYMBOL
बनाम EXPORT_SYMBOL_GPL
).
जीकेआई बिल्ड और बिल्ड के बीच Module.symvers
फ़ाइलों की तुलना की जा सकती है
ताकि vmlinux
से एक्सपोर्ट किए गए सिंबल में सीआरसी अंतर हो. अगर vmlinux
से एक्सपोर्ट किए गए किसी सिंबल में सीआरसी वैल्यू का अंतर है और उस सिंबल का इस्तेमाल आपके डिवाइस में लोड किए गए किसी मॉड्यूल में किया जाता है, तो मॉड्यूल लोड नहीं होता.
अगर आपके पास सभी बिल्ड आर्टफ़ैक्ट नहीं हैं, लेकिन आपके पास GKI कर्नेल और आपके कर्नेल की vmlinux
फ़ाइलें हैं, तो किसी खास सिंबल के लिए सीआरसी वैल्यू की तुलना की जा सकती है. इसके लिए, दोनों कर्नेल पर यह कमांड चलाएं और आउटपुट की तुलना करें:
nm <path to vmlinux>/vmlinux | grep __crc_<symbol name>
उदाहरण के लिए, यह कमांड module_layout
सिंबल के लिए सीआरसी वैल्यू की जांच करता है:
nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout
सीआरसी मेल न खाने की समस्या ठीक करें
मॉड्यूल लोड करते समय, सीआरसी के मेल न खाने की समस्या को हल करने के लिए, नीचे दिया गया तरीका अपनाएं:
--kbuild_symtypes
विकल्प का इस्तेमाल करके, GKI kernel और अपने डिवाइस का kernel बनाएं. इसके लिए, यह कमांड इस्तेमाल करें:tools/bazel run --kbuild_symtypes //common:kernel_aarch64_dist
यह कमांड, हर
.o
फ़ाइल के लिए एक.symtypes
फ़ाइल जनरेट करता है. यहां जाएं: Kleaf मेंKBUILD_SYMTYPES
देखें.Android 13 और उससे पहले के वर्शन के लिए, GKI kernel और अपने डिवाइस के kernel को इकट्ठा करें. इसके लिए, kernel को इकट्ठा करने के लिए इस्तेमाल किए जाने वाले कमांड के आगे
KBUILD_SYMTYPES=1
जोड़ें, जैसा कि इस कमांड में दिखाया गया है:KBUILD_SYMTYPES=1 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
build_abi.sh,
का इस्तेमाल करने पर,KBUILD_SYMTYPES=1
फ़्लैग पहले से ही सेट होता है.उस
.c
फ़ाइल को खोजें जिसमें सीआरसी से मेल न खाने वाले सिंबल को एक्सपोर्ट किया गया है. इसके लिए, इसका इस्तेमाल करें ये निर्देश देंगे:cd common && git grep EXPORT_SYMBOL.*module_layout kernel/module.c:EXPORT_SYMBOL(module_layout);
.c
फ़ाइल से जुड़ी.symtypes
फ़ाइल, GKI और आपके डिवाइस के कर्नेल बिल्ड आर्टफ़ैक्ट में मौजूद होती है..c
फ़ाइल को ढूंढने के लिए, इनका इस्तेमाल करें आदेश:cd out/$BRANCH/common && ls -1 kernel/module.* kernel/module.o kernel/module.o.symversions kernel/module.symtypes
.c
फ़ाइल की ये विशेषताएं हैं:.c
फ़ाइल का फ़ॉर्मैट, हर सिंबल के लिए एक (संभावित रूप से बहुत लंबी) लाइन है.लाइन की शुरुआत में मौजूद
[s|u|e|etc]#
का मतलब है कि सिंबल, डेटा टाइप के तौर पर मौजूद है[struct|union|enum|etc]
. उदाहरण के लिए:t#bool typedef _Bool bool
लाइन की शुरुआत में
#
का प्रीफ़िक्स मौजूद न होने से यह पता चलता है कि सिंबल एक फ़ंक्शन है. उदाहरण के लिए:find_module s#module * find_module ( const char * )
दोनों फ़ाइलों की तुलना करें और उनमें मौजूद अंतरों को ठीक करें.
पहला केस: डेटा टाइप दिखने की वजह से डेटा में अंतर दिखना
यदि एक कर्नेल किसी प्रतीक या डेटा प्रकार को मॉड्यूल के लिए अपारदर्शी बनाए रखता है और दूसरा
कर्नेल में काम नहीं करता है, यह फ़र्क़ .symtypes
फ़ाइलों के बीच दिखता है
दो कर्नेल का एक छोटा हिस्सा. किसी एक कर्नेल की .symtypes
फ़ाइल में UNKNOWN
है
और अन्य कर्नेल की .symtypes
फ़ाइल में बड़ा किया गया व्यू है
का चिह्न या डेटा टाइप शामिल करें.
उदाहरण के लिए,
आपकी कर्नेल में include/linux/device.h
फ़ाइल की वजह से सीआरसी मेल नहीं खाता, इनमें से एक
module_layout()
के लिए है:
#include <linux/fwnode.h>
उस चिह्न के लिए module.symtypes
की तुलना करने पर यह जानकारी मिलती है
अंतर:
$ 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 ] ; }
...
अगर आपके कर्नेल की वैल्यू UNKNOWN
है और जीकेआई कर्नेल में बड़ा किया गया व्यू है
का निशान लगा कर (बहुत कम संभावना है) का इस्तेमाल करता है, फिर नवीनतम Android Common कर्नेल को
ताकि आप सबसे नए GKI के कर्नेल बेस का इस्तेमाल कर सकें.
ज़्यादातर मामलों में, GKI केर्नेल की वैल्यू UNKNOWN
होती है. हालांकि, आपके केर्नेल में किए गए बदलावों की वजह से, आपके केर्नेल में सिंबल की इंटरनल जानकारी होती है. ऐसा इसलिए होता है, क्योंकि आपके कर्नेल में मौजूद किसी फ़ाइल ने ऐसा #include
जोड़ा है जो GKI कर्नेल में मौजूद नहीं है.
अक्सर, यह समस्या नए #include
को genksyms
से छिपा देती है.
#ifndef __GENKSYMS__
#include <linux/fwnode.h>
#endif
या फिर, अंतर पैदा करने वाले #include
का पता लगाने के लिए, इन निर्देशों का पालन करें
कदम:
वह हेडर फ़ाइल खोलें जिसमें इस अंतर वाले सिंबल या डेटा टाइप के बारे में बताया गया है. उदाहरण के लिए,
struct fwnode_handle
के लिएinclude/linux/fwnode.h
में बदलाव करें.हेडर फ़ाइल के सबसे ऊपर यह कोड जोड़ें:
#ifdef CRC_CATCH #error "Included from here" #endif
मॉड्यूल की
.c
फ़ाइल में जिसमें सीआरसी मेल नहीं खाता, जोड़ें को किसी भी#include
पंक्ति के पहले पहली पंक्ति के रूप में लिखें.#define CRC_CATCH 1
अपना मॉड्यूल कंपाइल करें. बिल्ड-टाइम की गड़बड़ी की वजह से, हेडर फ़ाइल
#include
जिसकी वजह से यह सीआरसी मेल नहीं खाता. उदाहरण के लिए: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"
#include
की इस चेन में मौजूद एक लिंक, आपके कोर में किए गए बदलाव की वजह से है. यह बदलाव GKI कोर में मौजूद नहीं है.बदलाव की पहचान करें, उसे अपने कर्नेल में वापस लाएं या उसे ACK पर अपलोड करें और मर्ज कर दें.
दूसरा मामला: डेटा टाइप में बदलाव की वजह से अंतर
अगर किसी सिंबल या डेटा टाइप के लिए सीआरसी मैच नहीं होता है, तो इसका मतलब है कि डेटा टाइप में बदलाव (जोड़ना, हटाना या बदलाव करना) हुआ है.
उदाहरण के लिए, अपने कर्नेल में नीचे दिया गया बदलाव करने से कई सीआरसी बनते हैं मैच नहीं करता, क्योंकि इस तरह के बदलाव से कई सिंबल पर सीधा असर पड़ता है:
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()
के लिए सीआरसी मेल नहीं खाता.
उस सिंबल के लिए .symtypes
फ़ाइलों की तुलना करने पर, यह इस तरह दिख सकता है:
$ 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 * ) ; ...
बदले गए टाइप की पहचान करने के लिए, यह तरीका अपनाएं:
सोर्स कोड में सिंबल की परिभाषा ढूंढें (आम तौर पर,
.h
फ़ाइलों में).- अपने कर्नेल और GKI कर्नेल के बीच सिंबल के अंतर के लिए, कमिट ढूंढने के लिए यह कमांड चलाएं:
git blame
- मिटाए गए सिंबल के लिए (जब ट्री में कोई सिंबल मिट जाता है और आपको को दूसरे ट्री में हटाना है), तो आपको वह परिवर्तन ढूंढना होगा रेखा हटा दी है. उस ट्री पर यह कमांड इस्तेमाल करें जहां लाइन मिटाई गई थी:
git log -S "copy paste of deleted line/word" -- <file where it was deleted>
बदलाव या मिटाए गए डेटा का पता लगाने के लिए, कमिट की गई फ़ाइलों की सूची देखें. शायद आपको पहला कमिट ही चाहिए. अगर ऐसा नहीं है, तो सूची में तब तक स्क्रोल करें, जब तक कि आपको ऐसेट से जुड़ी पूरी जानकारी नहीं मिल जाती.
बदलाव की पहचान करने के बाद, उसे अपने कर्नेल में वापस लाएं या उसे ACK पर अपलोड करें और उसे मर्ज कराएं.