Android कर्नेल एबीआई मॉनिटरिंग

ऐप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) मॉनिटरिंग टूल का इस्तेमाल किया जा सकता है. यह टूल इसमें उपलब्ध है Android 11 और उसके बाद के वर्शन, इन-कर्नेल को स्थिर रखने के लिए Android कर्नेल का एबीआई. यह टूल, एबीआई के प्रतिनिधित्व को इकट्ठा करता है और उनकी तुलना करता है मौजूदा कर्नेल बाइनरी (vmlinux+ GKI मॉड्यूल) से. ये एबीआई प्रतिनिधित्व, .stg फ़ाइलें और प्रतीक सूचियां होती हैं. इंटरफ़ेस जो प्रज़ेंटेशन से एक व्यू मिलता है उसे केर्नेल मॉड्यूल इंटरफ़ेस कहा जाता है (केएमआई). इस टूल का इस्तेमाल, केएमआई में हुए बदलावों को ट्रैक करने और कम करने के लिए किया जा सकता है.

यह एबीआई मॉनिटरिंग टूल एओएसपी में बनाया गया और इस्तेमाल एसटीजी (या libabigail इंच Android 13 और उससे पहले वाले वर्शन के लिए) प्रतिनिधित्व.

इस पेज पर एबीआई को इकट्ठा करने और उसका विश्लेषण करने के टूल के बारे में बताया गया है और स्थायित्व बनाए रखने के लिए, इन-कर्नेल ABI. इस पेज पर, बदलावों के बारे में जानकारी भी दी गई है Android कर्नेल के लिए.

प्रोसेस

कर्नेल के एबीआई का विश्लेषण कई चरणों में होता है, जिनमें से ज़्यादातर चरण अपने-आप होते हैं:

  1. कर्नेल और उसका एबीआई रिप्रज़ेंटेशन बनाएं.
  2. बिल्ड और पहचान फ़ाइल के बीच एबीआई के अंतर का विश्लेषण करें.
  3. एबीआई रिप्रज़ेंटेशन को अपडेट करें (अगर ज़रूरी हो).
  4. सिंबल वाली सूचियों के साथ काम करें.

नीचे दिए गए निर्देश किसी भी कर्नेल का इस्तेमाल करें जिसे इस्तेमाल किए जा सकने वाले टूलचेन (जैसे कि पहले से बने Clang टूलचेन). repo manifests Android के सभी कॉमन कर्नेल ब्रांचों और कई खास तौर पर किसी डिवाइस के लिए तैयार की गई हैं. ये पक्का करती हैं कि सही टूलचेन का इस्तेमाल किया जाए विश्लेषण के लिए एक कर्नेल डिस्ट्रिब्यूशन बनाएं.

सिंबल की सूचियां

KMI में कर्नेल में सभी प्रतीक या यहां तक कि 30,000+ एक्सपोर्ट किए गए सिंबल. इसके बजाय, वेंडर मॉड्यूल में इन सिंबल का इस्तेमाल किया जा सकता है रूट में सार्वजनिक रूप से रखी गई, सिंबल की सूची वाली फ़ाइलों के सेट में साफ़ तौर पर शामिल होनी चाहिए कर्नेल ट्री की एक वैल्यू होती है. सिंबल वाली सूची की सभी फ़ाइलों में मौजूद सभी सिंबल को एक साथ मिलाता है केएमआई सिंबल के उस सेट को तय करता है जिसे स्टेबल माना जाता है. सिंबल की सूची वाली फ़ाइल का उदाहरण इससे मेल खाता है abi_gki_anch64_db845c, जो कीवर्ड के लिए ज़रूरी सिंबल के बारे में बताता है DragonBoard 845c.

केवल किसी प्रतीक सूची में सूचीबद्ध प्रतीक और उनसे संबंधित संरचना और परिभाषाओं को केएमआई का हिस्सा माना जाता है. आप अपनी चिह्न सूची जोड़ देता है. नए इंटरफ़ेस के आने के बाद इनमें सिंबल की सूची शामिल होती है और ये KMI की जानकारी का हिस्सा होते हैं. साथ ही, उन्हें हमेशा के लिए बनाए रखा जाता है और इसे प्रतीक सूची से निकाला या संशोधित नहीं किया जाना चाहिए फ़्रीज़ किया गया.

हर Android Common Kernel (ACK) KMI कर्नेल ब्रांच में, सिंबल का अपना सेट होता है सूचियां. अलग-अलग KMI कर्नेल के बीच एबीआई स्थिरता देने की कोई कोशिश नहीं की गई है शाखाएं. उदाहरण के लिए, android12-5.10 के लिए केएमआई की वैल्यू इनसे पूरी तरह अलग है android13-5.10 के लिए केएमआई देख सकते हैं.

यह तय करने के लिए कि किस इंटरफ़ेस को मॉनिटर किया जाना चाहिए, एबीआई टूल, KMI सिंबल की सूचियों का इस्तेमाल करता है स्थिरता. कॉन्टेंट बनाने मुख्य सिंबल की सूची इसमें ऐसे सिंबल शामिल हैं जो GKI के कर्नेल मॉड्यूल के लिए ज़रूरी हैं. वेंडर हैं अतिरिक्त प्रतीक सूचियों को सबमिट और अपडेट करने की उम्मीद की जाती है ताकि यह सुनिश्चित किया जा सके ऐसे इंटरफ़ेस जो एबीआई के साथ काम करते हैं. उदाहरण के लिए, अगर आपको के लिए प्रतीक सूचियों का android13-5.15, इसे देखें https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android

सिंबल की सूची में वे सिंबल होते हैं जो किसी खास इवेंट के लिए ज़रूरी होते हैं विक्रेता या डिवाइस. टूल में इस्तेमाल की गई पूरी सूची, KMI सिंबल की सूची वाली फ़ाइलें. एबीआई टूल, हर सिंबल की जानकारी तय करते हैं. जैसे, फ़ंक्शन सिग्नेचर और नेस्ट किए गए डेटा स्ट्रक्चर.

केएमआई के फ़्रीज़ होने पर, मौजूदा केएमआई इंटरफ़ेस में कोई बदलाव करने की अनुमति नहीं होती; वे स्थिर हैं. हालांकि, वेंडर किसी भी समय केएमआई में सिंबल जोड़ सकते हैं जब तक कि जोड़े जाने से मौजूदा एबीआई की स्थिरता पर कोई असर नहीं पड़ता. नई जोड़ी गई केएमआई की सूची में मौजूद चिह्नों का उल्लेख करते ही, उन्हें स्थायी तौर पर बनाए रखा जाता है. कर्नेल के लिए सूची से सिंबल तब तक नहीं हटाए जाने चाहिए, जब तक उनकी पुष्टि नहीं की जाती कि किसी भी डिवाइस ने उस सिंबल पर निर्भरता के साथ कभी भी शिपिंग नहीं की है.

यहां दिए गए निर्देशों का पालन करके, किसी डिवाइस के लिए KMI के सिंबल की सूची जनरेट की जा सकती है सिंबल वाली सूचियों के साथ काम करने का तरीका. कई पार्टनर, ACK के हिसाब से एक सिंबल की सूची सबमिट करते हैं. हालांकि, ऐसा करना ज़रूरी नहीं है. अगर इससे रखरखाव में मदद मिलती है, तो सिंबल की एक से ज़्यादा सूचियां सबमिट की जा सकती हैं.

केएमआई को बढ़ाएं

केएमआई सिंबल और उनसे जुड़े स्ट्रक्चर को स्थायी तौर पर बनाए रखा जाता है (मतलब, ऐसे बदलाव जो फ़्रीज़ किए गए KMI के साथ कर्नेल में स्थिर इंटरफ़ेस को तोड़ते हैं स्वीकार किए जाते हैं) जीकेआई कर्नेल एक्सटेंशन के लिए खुला रहता है, ताकि डिवाइस शिपिंग कर सकें उन्हें यह तय करने की ज़रूरत नहीं है कि साल के आखिर में फ़्रीज़ किया गया. केएमआई की सीमा बढ़ाने के लिए, केएमआई में नए सिंबल जोड़े जा सकते हैं एक्सपोर्ट किए गए मौजूदा कर्नेल फ़ंक्शन, भले ही केएमआई फ़्रीज़ हो. नया कर्नेल अगर पैच केएमआई का उल्लंघन नहीं करते, तो उन्हें भी स्वीकार किया जा सकता है.

केएमआई की गड़बड़ी के बारे में जानकारी

कर्नेल में सोर्स होते हैं और इन सोर्स से बाइनरी बनाई जाती हैं. एबीआई की निगरानी वाले कर्नेल ब्रांच में, मौजूदा जीकेआई का एबीआई प्रतिनिधि शामिल है एबीआई (.stg फ़ाइल के रूप में). बाइनरी के बाद (vmlinux, Image और बनाए जाते हैं, तो एबीआई के प्रतिनिधित्व को बाइनरी. कर्नेल सोर्स फ़ाइल में किया गया कोई भी बदलाव, बाइनरी और टर्न निकाले गए .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 सिंबल की सूची अपडेट करें (देखें एबीआई की जानकारी अपडेट करना). उदाहरण के लिए को ABI XML और ACK में चिह्न सूची अपडेट करने के लिए, aosp/1367601 पर टैप करें.

कर्नेल ABI ब्रेकेज का समाधान करें

यूआरएल में बदलाव न करने के लिए, कोड को रीफ़ैक्टर करके, कर्नेल एबीआई ब्रेकेज को मैनेज किया जा सकता है एबीआई या एबीआई रिपोर्ट को अपडेट करना. इनका इस्तेमाल करें चार्ट देखकर जानें कि आपके लिए सबसे सही तरीका कौनसा है.

एबीआई ब्रेकेज फ़्लो चार्ट

पहला डायग्राम. एबीआई की गड़बड़ी का रिज़ॉल्यूशन

एबीआई में बदलावों से बचने के लिए, कोड को रीफ़ैक्टर करें

मौजूदा एबीआई में बदलाव करने से बचने की पूरी कोशिश करें. कई मामलों में, आपको एबीआई पर असर डालने वाले बदलावों को हटाने के लिए, अपने कोड को रीफ़ैक्टर करें.

  • स्ट्रक्चर फ़ील्ड में किए गए बदलावों को रीफ़ैक्टर करना. अगर किसी बदलाव की वजह से डीबग के लिए एबीआई में बदलाव होता है सुविधा के लिए, फ़ील्ड के आस-पास (स्ट्रक्चर और सोर्स में) #ifdef जोड़ें रेफ़रंस) और पक्का करें कि #ifdef के लिए इस्तेमाल किया गया CONFIG इसके लिए बंद हो प्रोडक्शन का defconfig और gki_defconfig इस्तेमाल कर सकता है. उदाहरण के लिए, डीबग करने का तरीका कॉन्फ़िगरेशन को एबीआई को तोड़े बिना, किसी स्ट्रक्चर में जोड़ा जा सकता है. इसके बारे में ज़्यादा जानने के लिए, यह पैचसेट.

  • मुख्य कर्नेल में बदलाव न करने के लिए, सुविधाओं को रीफ़ैक्टर करना. अगर नई सुविधाओं की ज़रूरत हो पार्टनर मॉड्यूल के साथ काम करने के लिए, ACK में जोड़ा जाना है. एबीआई को फिर से बनाने की कोशिश करें बदलाव का हिस्सा होना चाहिए. उदाहरण के लिए, मौजूदा कर्नेल ABI को बदले बिना अतिरिक्त क्षमताएं जोड़ने के लिए कर्नेल ABI का मतलब है aosp/1312213 पर टैप करें.

Android Gerrit पर काम न करने वाले एबीआई को ठीक करना

अगर आपने जान-बूझकर एबीआई को तोड़ने नहीं दिए हैं, तो आपको जांच करनी होगी, एबीआई मॉनिटरिंग टूल के दिशा-निर्देशों का इस्तेमाल करके. सबसे ज़्यादा खाया गया खाना ब्रेकेज की वजहें, बदले हुए डेटा स्ट्रक्चर और उनसे जुड़े सिंबल सीआरसी हैं बदलाव या कॉन्फ़िगरेशन विकल्प में होने वाले बदलावों की वजह से होता है. टूल से मिली समस्याओं को हल करके शुरुआत करें.

एबीआई के नतीजों को स्थानीय तौर पर फिर से देखा जा सकता है. कर्नेल और उसका एबीआई रिप्रज़ेंटेशन बनाएं.

लिंट-1 लेबल के बारे में जानकारी

अगर फ़्रीज़ या फ़ाइनल केएमआई वाली किसी ब्रांच में बदलाव अपलोड किए जाते हैं, तो बदलावों को AbiAnalyzer के बाद वाली प्रोसेस को पूरा करना होगा, ताकि यह पक्का किया जा सके कि बदलाव स्टेबल चैनल पर असर न डालें एबीआई का इस्तेमाल नहीं किया जा सकता. इस प्रोसेस के दौरान, AbiAnalyzer एबीआई रिपोर्ट, जो बिल्ड के दौरान बनाई जाती है. यह एक एक्सटेंडेड बिल्ड होता है, जो एबीआई को एक्सट्रैक्ट करने और उनकी तुलना करने के कुछ चरणों को पूरा करता है.

अगर AbiAnalyzer को कोई ऐसी रिपोर्ट मिलती है जो खाली नहीं है, तो वह Lent-1 लेबल सेट करती है और बदलाव को सबमिट करने से तब तक ब्लॉक किया गया है, जब तक कि इस समस्या को हल नहीं कर लिया जाता; जब तक पैचसेट को लिंट+1 लेबल.

कर्नेल एबीआई को अपडेट करें

अगर एबीआई में बदलाव नहीं किया जा सकता, तो आपको अपने कोड में बदलाव करने होंगे, को ABI के रेखांकन और प्रतीक सूची को ACK में बदल दिया जाता है. लिंट से -1 को हटाएं और GKI के साथ काम करने की सुविधा पर रोक न लगाएं. इसके लिए, यह तरीका अपनाएं:

  1. कोड में किए गए बदलावों को ACK में अपलोड करना.

  2. पैचसेट के लिए कोड-समीक्षा +2 मिलने की इंतज़ार करें.

  3. पहचान फ़ाइल को एबीआई के तौर पर दिखाने के तरीके को अपडेट करें.

  4. अपने कोड और एबीआई में हुए बदलावों को मर्ज करें.

एबीआई कोड में किए गए बदलावों को ACK में अपलोड करें

ACK ABI को अपडेट किए जाने के तरीके पर निर्भर करता है.

  • अगर एबीआई में कोई बदलाव किसी ऐसी सुविधा से जुड़ा है जो सीटीएस या वीटीएस टेस्ट पर असर डालता है, तो के लिए आम तौर पर ACK पर ध्यान दिया जा सकता है. जैसे:

  • अगर एबीआई में कोई बदलाव किसी ऐसी सुविधा के लिए है जिसे ACK के साथ शेयर किया जा सकता है, तो की अपनी ज़रूरतों के हिसाब से बदलाव के लिए, ACK पर ध्यान दिया जा सकता है. उदाहरण के लिए, नीचे दिए गए बदलाव CTS या VTS के लिए ज़रूरी नहीं हैं, लेकिन इन्हें ACK के साथ शेयर किया जा सकता है:

  • अगर एबीआई में किसी बदलाव से कोई ऐसी नई सुविधा मिलती है जिसे शामिल करने की ज़रूरत नहीं है के रूप में, तो आप स्टब का इस्तेमाल करके ACK में प्रतीकों का परिचय दे सकते हैं, जैसा कि यहां बताया गया है पढ़ें.

ACK के लिए स्टब का इस्तेमाल करना

स्टब सिर्फ़ उन मुख्य कर्नेल बदलावों के लिए ज़रूरी होने चाहिए जिनसे ACK, जैसे कि परफ़ॉर्मेंस और पावर में बदलाव. सूची की जानकारी के ये उदाहरण GKI के लिए ACK में स्टब और आंशिक चेरी-पिक्स के बारे में जानकारी.

  • कोर-आइसोलेट फ़ीचर स्टब (aosp/1284493). ACK में क्षमताएं होना ज़रूरी नहीं हैं, लेकिन सिंबल मौजूद होने चाहिए का इस्तेमाल करें, ताकि आपके मॉड्यूल इन प्रतीकों का इस्तेमाल कर सकें.

  • वेंडर मॉड्यूल के लिए प्लेसहोल्डर सिंबल (aosp/1288860).

  • हर प्रोसेस के हिसाब से सिर्फ़ एबीआई के लिए चेरी-पिक mm इवेंट ट्रैकिंग सुविधा (aosp/1288454). ओरिजनल पैच को ACK में चेरी के तौर पर चुना गया था. इसके बाद, उसमें काट-छांट की गई थी, ताकि सिर्फ़ task_struct के लिए एबीआई के अंतर को ठीक करने के लिए, ज़रूरी बदलाव करने होंगे और mm_event_count. यह पैच mm_event_type ईनम को भी अपडेट करता है, ताकि इसमें शामिल किया जा सके और पैसे चुका सकते हैं.

  • थर्मल स्ट्रक्चर वाले एबीआई में कुछ बदलाव किए गए हैं. इन बदलावों को लागू करने के लिए नए एबीआई फ़ील्ड जोड़े जा सकते हैं.

    • पैच एओएसपी/1255544 पार्टनर कर्नेल और ACK के बीच ABI के अंतर का समाधान किया गया.

    • पैच एओएसपी/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() का इस्तेमाल करके एक्सपोर्ट किए गए चिह्न) चिह्न सूची. अन्य सभी सिंबल को एक्सपोर्ट नहीं किया जाता है और वे एक मॉड्यूल लोड कर रहे हैं जिसके लिए एक्सपोर्ट नहीं किया गया चिह्न अस्वीकार किया गया. यह पाबंदी, बिल्ड के समय लागू की जाती है और छूटी हुई एंट्री फ़्लैग की जाती हैं.

डेवलपमेंट के मकसद से, ऐसे जीकेआई कर्नेल बिल्ड का इस्तेमाल किया जा सकता है जिसमें सिंबल को ट्रिम करना (इसका मतलब है कि एक्सपोर्ट किए गए सभी सिंबल इस्तेमाल किए जा सकते हैं). पता लगाने के लिए ये बिल्ड. kernel_debug_aarch64 बिल्ड में देखें ci.android.com.

मॉड्यूल वर्शन का इस्तेमाल करके, केएमआई लागू करें

जेनेरिक कर्नेल इमेज (जीकेआई) के कर्नेल, मॉड्यूल वर्शन का इस्तेमाल करते हैं (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 ''

मॉड्यूल वर्शन का इस्तेमाल

मॉड्यूल वर्शनिंग इन वजहों से फ़ायदेमंद है:

  • मॉड्यूल वर्शनिंग की वजह से, डेटा स्ट्रक्चर की विज़िबिलिटी में बदलाव हो जाता है. अगर मॉड्यूल ओपेक डेटा स्ट्रक्चर में बदलाव करना. इसमें ऐसे डेटा स्ट्रक्चर होते हैं जो केएमआई, स्ट्रक्चर में भविष्य में होने वाले बदलावों के बाद वे टूट जाते हैं.

    उदाहरण के लिए, fwnode struct device में फ़ील्ड है. यह फ़ील्ड, मॉड्यूल के बारे में साफ़ तौर पर नहीं बताया जाना चाहिए. ऐसा इसलिए, ताकि वे इसमें बदलाव न कर सकें device->fw_node के फ़ील्ड या इसके आकार के बारे में अनुमान लगाएं.

    हालांकि, अगर किसी मॉड्यूल में <linux/fwnode.h> (सीधे तौर पर या किसी अन्य तरीके से) शामिल है, तो तो struct device में मौजूद fwnode फ़ील्ड अब ओपेक नहीं है. कॉन्टेंट बनाने मॉड्यूल फिर device->fwnode->dev में बदलाव कर सकता है या device->fwnode->ops. यह स्थिति कई वजहों से मुश्किल है. यहां बताया गया है:

    • यह उन अनुमानों को तोड़ सकता है जिन्हें कोर कर्नेल कोड, अपने अंदरूनी काम के बारे में बना रहा है डेटा स्ट्रक्चर.

    • अगर आने वाले समय में किसी कर्नेल अपडेट से, struct fwnode_handle (डेटा fwnode प्रकार) है, तो मॉड्यूल अब नए कर्नेल के साथ काम नहीं करता है. इसके अलावा, मॉड्यूल काम न करने की वजह से, stgdiff कोई अंतर नहीं दिखाएगा केएमआई को इंटरनल डेटा स्ट्रक्चर के साथ सीधे तौर पर छेड़छाड़ करके, डेटा को सिर्फ़ बाइनरी रिप्रज़ेंटेशन की जांच करके कैप्चर किया जा सकता है.

  • अगर किसी मौजूदा मॉड्यूल को बाद में लोड किया जाता है, तो यह माना जाता है कि वह KMI के साथ काम नहीं करता जो कि असंगत है. मॉड्यूल वर्शनिंग, रन-टाइम चेक जोड़ता है गलती से ऐसे मॉड्यूल को लोड होने से बचाएं जो कर्नेल के साथ KMI के साथ काम न करता हो. यह जांच मुश्किल से डीबग करने वाली रनटाइम समस्याओं और कर्नेल क्रैश को रोकती है के एमआई की जांच करने के नतीजे का पता नहीं चला.

मॉड्यूल वर्शनिंग चालू करने से, इन सभी समस्याओं से बचा जा सकता है.

डिवाइस को चालू किए बिना, सीआरसी मेल नहीं खाने की जांच करें

stgdiff अन्य के साथ कर्नेल के बीच CRC बेमेल की तुलना और रिपोर्ट करता है एबीआई में अंतर.

इसके अलावा, CONFIG_MODVERSIONS सक्षम के साथ एक पूरा कर्नेल बिल्ड जनरेट करता है Module.symvers फ़ाइल का इस्तेमाल किया जा सकता है. इस फ़ाइल में एक कर्नेल (vmlinux) और मॉड्यूल से एक्सपोर्ट किए गए हर चिह्न की लाइन. हर लाइन में सीआरसी वैल्यू, सिंबल का नाम, सिंबल का नेमस्पेस, vmlinux या सिंबल को एक्सपोर्ट करने वाले मॉड्यूल का नाम और एक्सपोर्ट टाइप (उदाहरण के लिए, EXPORT_SYMBOL बनाम EXPORT_SYMBOL_GPL).

जीकेआई बिल्ड और बिल्ड के बीच Module.symvers फ़ाइलों की तुलना की जा सकती है ताकि vmlinux से एक्सपोर्ट किए गए सिंबल में सीआरसी अंतर हो. अगर वहां vmlinux से एक्सपोर्ट किए गए किसी भी सिंबल में सीआरसी वैल्यू का अंतर है और चिह्न का इस्तेमाल डिवाइस में लोड किए गए किसी मॉड्यूल के लिए किया जाता है, लेकिन मॉड्यूल नहीं लोड होता है.

अगर आपके पास सभी बिल्ड आर्टफ़ैक्ट नहीं हैं, लेकिन आपके पास इसकी vmlinux फ़ाइलें हैं जीकेआई कर्नेल और आपके कर्नेल के बीच, किसी खास यूआरएल के लिए सीआरसी वैल्यू की तुलना कर्नेल पर निम्नलिखित कमांड चलाकर और दोनों की तुलना करके प्रतीक आउटपुट:

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

उदाहरण के लिए, नीचे दिया गया निर्देश, module_layout के लिए सीआरसी वैल्यू की जांच करता है चिह्न:

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

सीआरसी मेल न खाने की समस्या ठीक करें

मॉड्यूल लोड करते समय, सीआरसी के मेल न खाने की समस्या को हल करने के लिए, नीचे दिया गया तरीका अपनाएं:

  1. --kbuild_symtypes का इस्तेमाल करके GKI कर्नेल और अपना डिवाइस कर्नेल बनाएँ विकल्प दिया गया है, जैसा कि नीचे दिए गए निर्देश में दिखाया गया है:

    tools/bazel run --kbuild_symtypes //common:kernel_aarch64_dist
    

    इस निर्देश से, हर .o फ़ाइल के लिए .symtypes फ़ाइल जनरेट होती है. यहां जाएं: Kleaf में KBUILD_SYMTYPES देखें.

    Android 13 और इससे पहले के वर्शन के लिए, GKI कर्नेल बनाएं और आपके डिवाइस कर्नेल को आपको निर्देश देने के लिए KBUILD_SYMTYPES=1 पहले से लिखना होगा कर्नेल को बनाने के लिए इस्तेमाल करें, जैसा कि नीचे दिए गए कमांड में दिखाया गया है:

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

    build_abi.sh, का इस्तेमाल करने पर, KBUILD_SYMTYPES=1 फ़्लैग अपने-आप सेट होता है पहले से मौजूद है.

  2. उस .c फ़ाइल को खोजें जिसमें सीआरसी से मेल न खाने वाले सिंबल को एक्सपोर्ट किया गया है. इसके लिए, इसका इस्तेमाल करें ये निर्देश देंगे:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
    
  3. .c फ़ाइल के पास, जीकेआई में .symtypes फ़ाइल होनी चाहिए. साथ ही, डिवाइस कर्नेल बिल्ड आर्टफ़ैक्ट. .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 * )
      
  4. दोनों फ़ाइलों की तुलना करें और सभी अंतर ठीक करें.

पहला केस: डेटा टाइप दिखने की वजह से डेटा में अंतर दिखना

यदि एक कर्नेल किसी प्रतीक या डेटा प्रकार को मॉड्यूल के लिए अपारदर्शी बनाए रखता है और दूसरा कर्नेल में काम नहीं करता है, यह फ़र्क़ .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 का पता लगाने के लिए, इन निर्देशों का पालन करें चरण:

  1. वह हेडर फ़ाइल खोलें जिसमें मौजूद सिंबल या डेटा टाइप के बारे में जानकारी दी गई हो अंतर. उदाहरण के लिए, include/linux/fwnode.h struct fwnode_handle.

  2. हेडर फ़ाइल के सबसे ऊपर यह कोड जोड़ें:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. मॉड्यूल की .c फ़ाइल में जिसमें सीआरसी मेल नहीं खाता, जोड़ें को #include पंक्तियों में से किसी भी पंक्ति के पहले पहली पंक्ति के रूप में लिखें.

    #define CRC_CATCH 1
    
  4. अपना मॉड्यूल कंपाइल करें. बिल्ड-टाइम की गड़बड़ी की वजह से, हेडर फ़ाइल #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 कर्नेल में मौजूद नहीं है.

  5. बदलाव की पहचान करें, उसे अपने कर्नेल में वापस लाएं या उसे 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 * ) ; ...

बदले गए टाइप की पहचान करने के लिए, यह तरीका अपनाएं:

  1. सोर्स कोड में सिंबल की परिभाषा ढूंढें (आम तौर पर, .h फ़ाइलों में).

    • आपके कर्नेल और GKI कर्नेल के बीच चिह्न अंतर के लिए, निम्न कमांड चलाकर कमिट को खोजें:
    git blame
    
    • मिटाए गए सिंबल के लिए (जब ट्री में कोई सिंबल मिट जाता है और आपको को दूसरे ट्री में हटाना है), तो आपको वह परिवर्तन ढूंढना होगा रेखा हटा दी है. जहां लाइन हटाया गया:
    git log -S "copy paste of deleted line/word" -- <file where it was deleted>
    
  2. बदलाव करने या मिटाने का पता लगाने के लिए, लौटाए गए कमिट की सूची की समीक्षा करें. कॉन्टेंट बनाने सबसे पहले कमिट करें वह चीज़ है जिसे आप खोज रहे हैं. अगर ऐसा नहीं है, तो सूची में तब तक स्क्रोल करें, जब तक कि आपको ऐसेट से जुड़ी पूरी जानकारी नहीं मिल जाती.

  3. बदलाव की पहचान करने के बाद, उसे अपने कर्नेल में वापस लाएं या इसे ACK पर अपलोड करें और इसे पाएं मर्ज किए गए.