অ্যান্ড্রয়েড কার্নেল এবিআই মনিটরিং

আপনি অ্যান্ড্রয়েড কার্নেলের ইন-কার্নেল ABI স্থিতিশীল করতে Android 11 এবং উচ্চতর সংস্করণে উপলব্ধ অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI) মনিটরিং টুলিং ব্যবহার করতে পারেন। টুলিং বিদ্যমান কার্নেল বাইনারি ( vmlinux + GKI মডিউল) থেকে ABI উপস্থাপনা সংগ্রহ ও তুলনা করে। এই ABI উপস্থাপনা হল .stg ফাইল এবং প্রতীক তালিকা। যে ইন্টারফেসটিতে উপস্থাপনা একটি দৃশ্য দেয় তাকে কার্নেল মডিউল ইন্টারফেস (KMI) বলা হয়। আপনি KMI-তে পরিবর্তনগুলি ট্র্যাক করতে এবং হ্রাস করতে টুলিং ব্যবহার করতে পারেন।

ABI মনিটরিং টুলিং AOSP-তে তৈরি করা হয়েছে এবং উপস্থাপনা তৈরি করতে এবং তুলনা করতে STG (বা Android 13 এবং তার থেকে কম সময়ে libabigail ) ব্যবহার করে।

এই পৃষ্ঠাটি টুলিং, ABI উপস্থাপনা সংগ্রহ ও বিশ্লেষণের প্রক্রিয়া এবং ইন-কারনেল ABI-কে স্থিতিশীলতা প্রদানের জন্য এই জাতীয় উপস্থাপনাগুলির ব্যবহার বর্ণনা করে। এই পৃষ্ঠাটি অ্যান্ড্রয়েড কার্নেলগুলিতে অবদান রাখার জন্য তথ্য সরবরাহ করে।

প্রক্রিয়া

কার্নেলের ABI বিশ্লেষণ একাধিক পদক্ষেপ নেয়, যার বেশিরভাগই স্বয়ংক্রিয় হতে পারে:

  1. কার্নেল এবং এর ABI উপস্থাপনা তৈরি করুন
  2. বিল্ড এবং একটি রেফারেন্সের মধ্যে ABI পার্থক্য বিশ্লেষণ করুন
  3. ABI প্রতিনিধিত্ব আপডেট করুন (যদি প্রয়োজন হয়)
  4. প্রতীক তালিকা নিয়ে কাজ করুন

নিম্নলিখিত নির্দেশাবলী যেকোন কার্নেলের জন্য কাজ করে যা আপনি একটি সমর্থিত টুলচেন ব্যবহার করে তৈরি করতে পারেন (যেমন প্রি-বিল্ট ক্ল্যাং টুলচেন)। repo manifests সমস্ত অ্যান্ড্রয়েড সাধারণ কার্নেল শাখার জন্য এবং বেশ কয়েকটি ডিভাইস-নির্দিষ্ট কার্নেলের জন্য উপলব্ধ, তারা নিশ্চিত করে যে আপনি বিশ্লেষণের জন্য একটি কার্নেল বিতরণ তৈরি করার সময় সঠিক টুলচেইন ব্যবহার করা হয়েছে।

প্রতীক তালিকা

KMI কার্নেলের সমস্ত চিহ্ন বা এমনকি 30,000+ রপ্তানি করা চিহ্নগুলির মধ্যেও অন্তর্ভুক্ত করে না। পরিবর্তে, বিক্রেতা মডিউল দ্বারা ব্যবহার করা যেতে পারে এমন চিহ্নগুলি কার্নেল গাছের মূলে সর্বজনীনভাবে রক্ষণাবেক্ষণ করা প্রতীক তালিকা ফাইলগুলির একটি সেটে স্পষ্টভাবে তালিকাভুক্ত করা হয়। সমস্ত প্রতীক তালিকা ফাইলের সমস্ত প্রতীকের মিলন স্থিতিশীল হিসাবে বজায় রাখা KMI প্রতীকগুলির সেটকে সংজ্ঞায়িত করে। একটি উদাহরণ প্রতীক তালিকা ফাইল হল abi_gki_aarch64_db845c , যা ড্রাগনবোর্ড 845c এর জন্য প্রয়োজনীয় চিহ্নগুলি ঘোষণা করে।

শুধুমাত্র একটি প্রতীক তালিকায় তালিকাভুক্ত চিহ্নগুলি এবং তাদের সম্পর্কিত কাঠামো এবং সংজ্ঞাগুলি কেএমআই-এর অংশ হিসাবে বিবেচনা করা হয়। আপনার প্রয়োজনীয় প্রতীক উপস্থিত না থাকলে আপনি আপনার প্রতীক তালিকায় পরিবর্তন পোস্ট করতে পারেন। নতুন ইন্টারফেসগুলি একটি প্রতীক তালিকায় থাকার পরে এবং KMI বর্ণনার অংশ হওয়ার পরে, সেগুলিকে স্থিতিশীল হিসাবে বজায় রাখা হয় এবং শাখাটি হিমায়িত হওয়ার পরে প্রতীক তালিকা থেকে সরানো বা সংশোধন করা উচিত নয়৷

প্রতিটি অ্যান্ড্রয়েড কমন কার্নেল (ACK) KMI কার্নেল শাখার নিজস্ব প্রতীক তালিকা রয়েছে। বিভিন্ন KMI কার্নেল শাখার মধ্যে ABI স্থিতিশীলতা প্রদানের কোনো প্রচেষ্টা করা হয় না। উদাহরণস্বরূপ, android12-5.10 এর KMI সম্পূর্ণরূপে android13-5.10 এর KMI থেকে স্বাধীন।

স্থিতিশীলতার জন্য কোন ইন্টারফেসগুলিকে নিরীক্ষণ করতে হবে তা সীমিত করতে ABI সরঞ্জামগুলি KMI প্রতীক তালিকা ব্যবহার করে। প্রধান প্রতীক তালিকায় GKI কার্নেল মডিউলগুলির জন্য প্রয়োজনীয় চিহ্নগুলি রয়েছে৷ বিক্রেতাদের আশা করা হচ্ছে যে তারা যে ইন্টারফেসের উপর নির্ভর করে তা নিশ্চিত করতে অতিরিক্ত প্রতীক তালিকা জমা এবং আপডেট করবে ABI সামঞ্জস্য বজায় রাখতে। উদাহরণস্বরূপ, android13-5.15 এর জন্য প্রতীক তালিকার একটি তালিকা দেখতে, https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android দেখুন

একটি প্রতীক তালিকায় নির্দিষ্ট বিক্রেতা বা ডিভাইসের জন্য প্রয়োজনীয় চিহ্নগুলি রয়েছে। টুল দ্বারা ব্যবহৃত সম্পূর্ণ তালিকা হল KMI প্রতীক তালিকা ফাইলগুলির সমস্ত মিলন। এবিআই টুলস ফাংশন সিগনেচার এবং নেস্টেড ডেটা স্ট্রাকচার সহ প্রতিটি চিহ্নের বিবরণ নির্ধারণ করে।

যখন KMI হিমায়িত হয়, তখন বিদ্যমান KMI ইন্টারফেসে কোনো পরিবর্তন অনুমোদিত হয় না; তারা স্থিতিশীল। যাইহোক, বিক্রেতারা যেকোনও সময় KMI-তে চিহ্ন যোগ করতে পারেন যতক্ষণ না সংযোজন বিদ্যমান ABI-এর স্থায়িত্বকে প্রভাবিত না করে। নতুন যোগ করা প্রতীকগুলি কেএমআই প্রতীক তালিকা দ্বারা উদ্ধৃত হওয়ার সাথে সাথে স্থিতিশীল হিসাবে বজায় রাখা হয়। একটি কার্নেলের জন্য একটি তালিকা থেকে চিহ্নগুলি সরানো উচিত নয় যদি না এটি নিশ্চিত করা যায় যে কোনও ডিভাইস সেই প্রতীকের উপর নির্ভরশীলতার সাথে পাঠানো হয়নি।

প্রতীক তালিকার সাথে কীভাবে কাজ করবেন তার নির্দেশাবলী ব্যবহার করে আপনি একটি ডিভাইসের জন্য একটি KMI প্রতীক তালিকা তৈরি করতে পারেন। অনেক অংশীদার ACK প্রতি একটি প্রতীক তালিকা জমা দেয়, কিন্তু এটি একটি কঠিন প্রয়োজনীয়তা নয়। এটি রক্ষণাবেক্ষণে সাহায্য করলে, আপনি একাধিক প্রতীক তালিকা জমা দিতে পারেন।

KMI প্রসারিত করুন

যদিও KMI চিহ্ন এবং সম্পর্কিত কাঠামো স্থিতিশীল হিসাবে রক্ষণাবেক্ষণ করা হয় (অর্থাৎ যে পরিবর্তনগুলি একটি হিমায়িত KMI সহ একটি কার্নেলে স্থিতিশীল ইন্টারফেসগুলিকে ভেঙে দেয় তা গ্রহণ করা যায় না) GKI কার্নেলটি এক্সটেনশনের জন্য উন্মুক্ত থাকে যাতে বছরের পরে শিপিং করা ডিভাইসগুলিকে সমস্ত সংজ্ঞায়িত করার প্রয়োজন না হয় KMI হিমায়িত হওয়ার আগে তাদের নির্ভরতা। KMI প্রসারিত করতে, আপনি KMI তে নতুন বা বিদ্যমান রপ্তানিকৃত কার্নেল ফাংশনের জন্য নতুন চিহ্ন যোগ করতে পারেন, এমনকি KMI হিমায়িত করা হলেও। নতুন কার্নেল প্যাচগুলিও গৃহীত হতে পারে যদি তারা KMI ভাঙে না।

KMI ভাঙ্গন সম্পর্কে

একটি কার্নেলের উত্স রয়েছে এবং সেই উত্সগুলি থেকে বাইনারি তৈরি করা হয়। ABI-মনিটর করা কার্নেল শাখাগুলির মধ্যে বর্তমান GKI ABI-এর একটি ABI প্রতিনিধিত্ব রয়েছে (একটি .stg ফাইল আকারে)। বাইনারিগুলি ( vmlinux , Image এবং যেকোনো GKI মডিউল) তৈরি হওয়ার পরে, বাইনারিগুলি থেকে একটি ABI উপস্থাপনা বের করা যেতে পারে। কার্নেল সোর্স ফাইলে করা যেকোনো পরিবর্তন বাইনারিগুলিকে প্রভাবিত করতে পারে এবং ফলস্বরূপ নিষ্কাশিত .stg প্রভাবিত করতে পারে। AbiAnalyzer বিশ্লেষক প্রতিশ্রুতিবদ্ধ .stg ফাইলটিকে বিল্ড আর্টিফ্যাক্ট থেকে প্রাপ্ত ফাইলের সাথে তুলনা করে এবং যদি এটি একটি শব্দার্থগত পার্থক্য খুঁজে পায় তবে গেরিট-এর পরিবর্তনের উপর একটি লিন্ট-1 লেবেল সেট করে।

ABI ভাঙ্গন হ্যান্ডেল

একটি উদাহরণ হিসাবে, নিম্নলিখিত প্যাচ একটি খুব সুস্পষ্ট ABI ভাঙ্গন প্রবর্তন করে:

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.

আপনি যখন এই প্যাচ প্রয়োগ করে বিল্ড এবিআই চালান, তখন টুলিং একটি নন-জিরো ত্রুটি কোড সহ প্রস্থান করে এবং এর মতো একটি ABI পার্থক্য রিপোর্ট করে:

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

বিল্ড টাইমে ABI পার্থক্য সনাক্ত করা হয়েছে

ত্রুটির সবচেয়ে সাধারণ কারণ হল যখন একজন ড্রাইভার কার্নেল থেকে একটি নতুন প্রতীক ব্যবহার করে যা প্রতীক তালিকার কোনোটিতে নেই।

যদি প্রতীকটি প্রতীক তালিকায় অন্তর্ভুক্ত না হয় ( android/abi_gki_aarch64 ), তাহলে আপনাকে প্রথমে যাচাই করতে হবে যে এটি EXPORT_SYMBOL_GPL( symbol_name ) দিয়ে রপ্তানি হয়েছে এবং তারপর ABI XML উপস্থাপনা এবং প্রতীক তালিকা আপডেট করুন৷ উদাহরণস্বরূপ, নিম্নলিখিত পরিবর্তনগুলি android-12-5.10 শাখায় নতুন ইনক্রিমেন্টাল FS বৈশিষ্ট্য যুক্ত করে, যার মধ্যে প্রতীক তালিকা এবং ABI XML উপস্থাপনা আপডেট করা অন্তর্ভুক্ত।

  • বৈশিষ্ট্য পরিবর্তনের উদাহরণ aosp/1345659 এ রয়েছে।
  • প্রতীক তালিকার উদাহরণ aosp/1346742 এ রয়েছে।
  • ABI XML পরিবর্তনের উদাহরণ 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 প্রতিনিধিত্ব আপডেট করুন )। ACK-এ ABI XML এবং প্রতীক তালিকা আপডেট করার উদাহরণের জন্য, aosp/1367601 পড়ুন।

কার্নেল ABI ভাঙ্গনের সমাধান করুন

আপনি ABI পরিবর্তন না করার জন্য কোড রিফ্যাক্টর করে বা ABI প্রতিনিধিত্ব আপডেট করে কার্নেল ABI ভাঙ্গনগুলি পরিচালনা করতে পারেন। আপনার পরিস্থিতির জন্য সর্বোত্তম পদ্ধতি নির্ধারণ করতে নিম্নলিখিত চার্টটি ব্যবহার করুন।

ABI ব্রেকেজ ফ্লো চার্ট

চিত্র 1. ABI ব্রেকেজ রেজোলিউশন

ABI পরিবর্তন এড়াতে রিফ্যাক্টর কোড

বিদ্যমান ABI পরিবর্তন এড়াতে সর্বাত্মক প্রচেষ্টা করুন। অনেক ক্ষেত্রে, আপনি ABI-কে প্রভাবিত করে এমন পরিবর্তনগুলি সরাতে আপনার কোড রিফ্যাক্টর করতে পারেন।

  • রিফ্যাক্টরিং কাঠামো ক্ষেত্রের পরিবর্তন। যদি কোনো পরিবর্তন একটি ডিবাগ বৈশিষ্ট্যের জন্য ABI-কে পরিবর্তন করে, তাহলে ক্ষেত্রগুলির চারপাশে একটি #ifdef যোগ করুন (স্ট্রাকট এবং সোর্স রেফারেন্সে) এবং নিশ্চিত করুন যে #ifdef এর জন্য ব্যবহৃত CONFIG প্রোডাকশন defconfig এবং gki_defconfig এর জন্য নিষ্ক্রিয় করা হয়েছে। কিভাবে একটি ডিবাগ কনফিগারেশন ABI না ভেঙে একটি স্ট্রাকটে যোগ করা যায় তার উদাহরণের জন্য, এই প্যাচসেটটি পড়ুন।

  • মূল কার্নেল পরিবর্তন না করার জন্য রিফ্যাক্টরিং বৈশিষ্ট্য। অংশীদার মডিউল সমর্থন করার জন্য ACK-তে নতুন বৈশিষ্ট্য যোগ করার প্রয়োজন হলে, কার্নেল ABI পরিবর্তন এড়াতে পরিবর্তনের ABI অংশটি রিফ্যাক্টর করার চেষ্টা করুন। কার্নেল পরিবর্তন না করে অতিরিক্ত কার্যকারিতা যোগ করার জন্য বিদ্যমান কার্নেল ABI ব্যবহার করার উদাহরণের জন্য aosp/1312213 দেখুন।

অ্যান্ড্রয়েড গেরিটে একটি ভাঙা ABI ঠিক করুন

আপনি যদি ইচ্ছাকৃতভাবে কার্নেল ABI ভাঙ্গন না, তাহলে ABI মনিটরিং টুলিং দ্বারা প্রদত্ত নির্দেশিকা ব্যবহার করে আপনাকে তদন্ত করতে হবে। ভাঙ্গনের সবচেয়ে সাধারণ কারণগুলি হল পরিবর্তিত ডেটা স্ট্রাকচার এবং সংশ্লিষ্ট চিহ্ন সিআরসি পরিবর্তন, অথবা কনফিগার বিকল্পের পরিবর্তনের কারণে যা উপরে উল্লিখিত যেকোনো একটির দিকে নিয়ে যায়। টুল দ্বারা পাওয়া সমস্যাগুলি সমাধান করে শুরু করুন।

আপনি স্থানীয়ভাবে ABI অনুসন্ধানগুলি পুনরুত্পাদন করতে পারেন, কার্নেল তৈরি করুন এবং এর ABI প্রতিনিধিত্ব দেখুন।

লিন্ট -1 লেবেল সম্পর্কে

আপনি যদি হিমায়িত বা চূড়ান্ত KMI ধারণ করে এমন একটি শাখায় পরিবর্তন আপলোড করেন, তবে পরিবর্তনগুলি একটি বেমানান উপায়ে স্থিতিশীল ABI-কে প্রভাবিত না করে তা নিশ্চিত করতে অবশ্যই AbiAnalyzer পাস করতে হবে। এই প্রক্রিয়া চলাকালীন, AbiAnalyzer বিল্ডের সময় তৈরি করা ABI রিপোর্টের সন্ধান করে (একটি বর্ধিত বিল্ড যা স্বাভাবিক বিল্ডটি সম্পাদন করে এবং তারপরে কিছু ABI নিষ্কাশন এবং তুলনা পদক্ষেপগুলি সম্পাদন করে।

যদি AbiAnalyzer একটি অ-খালি রিপোর্ট খুঁজে পায় তবে এটি Lint-1 লেবেল সেট করে এবং পরিবর্তনটি সমাধান না হওয়া পর্যন্ত জমা দেওয়া থেকে ব্লক করা হয়; যতক্ষণ না প্যাচসেট একটি Lint+1 লেবেল পায়।

কার্নেল ABI আপডেট করুন

যদি ABI পরিবর্তন করা অনিবার্য হয়, তাহলে আপনাকে অবশ্যই আপনার কোড পরিবর্তন, ABI উপস্থাপনা এবং প্রতীক তালিকা ACK-এ প্রয়োগ করতে হবে। লিন্টকে -1 অপসারণ করতে এবং GKI সামঞ্জস্য না ভাঙতে, এই পদক্ষেপগুলি অনুসরণ করুন:

  1. ACK এ আপলোড কোড পরিবর্তন

  2. প্যাচসেটের জন্য একটি কোড-রিভিউ +2 পাওয়ার জন্য অপেক্ষা করুন।

  3. রেফারেন্স ABI প্রতিনিধিত্ব আপডেট করুন

  4. আপনার কোড পরিবর্তন এবং ABI আপডেট পরিবর্তন মার্জ.

ACK এ ABI কোড পরিবর্তন আপলোড করুন

ACK ABI আপডেট করা পরিবর্তনের ধরনের উপর নির্ভর করে।

  • যদি ABI পরিবর্তন এমন একটি বৈশিষ্ট্যের সাথে সম্পর্কিত হয় যা CTS বা VTS পরীক্ষাগুলিকে প্রভাবিত করে, তবে পরিবর্তনটি সাধারণত ACK-এ চেরি-পিক করা যেতে পারে। উদাহরণ স্বরূপ:

    • অডিও কাজ করার জন্য aosp/1289677 প্রয়োজন।
    • ইউএসবি কাজ করার জন্য aosp/1295945 প্রয়োজন।
  • যদি ABI পরিবর্তন এমন একটি বৈশিষ্ট্যের জন্য হয় যা ACK এর সাথে ভাগ করা যেতে পারে, তাহলে সেই পরিবর্তনটি ACK-এ চেরি-পিক করা যেতে পারে। উদাহরণস্বরূপ, CTS বা VTS পরীক্ষার জন্য নিম্নলিখিত পরিবর্তনগুলির প্রয়োজন নেই কিন্তু ACK এর সাথে শেয়ার করা ঠিক আছে:

    • aosp/1250412 একটি তাপীয় বৈশিষ্ট্য পরিবর্তন।
    • aosp/1288857 হল একটি EXPORT_SYMBOL_GPL পরিবর্তন৷
  • যদি একটি ABI পরিবর্তন একটি নতুন বৈশিষ্ট্য প্রবর্তন করে যা ACK-তে অন্তর্ভুক্ত করার প্রয়োজন নেই, তাহলে আপনি নিম্নলিখিত বিভাগে বর্ণিত হিসাবে একটি স্টাব ব্যবহার করে ACK-তে প্রতীকগুলি প্রবর্তন করতে পারেন।

ACK এর জন্য স্টাব ব্যবহার করুন

স্টাবগুলি শুধুমাত্র মূল কার্নেল পরিবর্তনের জন্য প্রয়োজনীয় হতে হবে যা ACK-এর উপকারে আসে না, যেমন কর্মক্ষমতা এবং শক্তি পরিবর্তন। GKI-এর জন্য ACK-এ স্টাব এবং আংশিক চেরি-পিকগুলির উদাহরণ নিম্নলিখিত তালিকায় রয়েছে।

  • কোর-আইসোলেট ফিচার স্টাব ( aosp/1284493 )। ACK-এর কার্যকারিতা প্রয়োজনীয় নয়, কিন্তু এই চিহ্নগুলি ব্যবহার করার জন্য আপনার মডিউলগুলিকে ACK-এ উপস্থিত থাকতে হবে।

  • বিক্রেতা মডিউল ( aosp/1288860 ) এর জন্য স্থানধারক প্রতীক।

  • প্রতি-প্রক্রিয়া mm ইভেন্ট ট্র্যাকিং বৈশিষ্ট্যের ABI-শুধুমাত্র চেরি-পিক ( aosp/1288454 )। আসল প্যাচটি ACK-এ চেরি-পিক করা হয়েছিল এবং তারপরে task_struct এবং mm_event_count এর জন্য ABI পার্থক্য সমাধানের জন্য শুধুমাত্র প্রয়োজনীয় পরিবর্তনগুলি অন্তর্ভুক্ত করার জন্য ছাঁটাই করা হয়েছিল। এই প্যাচটি চূড়ান্ত সদস্যদের ধারণ করার জন্য mm_event_type enum আপডেট করে।

  • তাপীয় কাঠামো ABI পরিবর্তনের আংশিক চেরি-পিক যা শুধুমাত্র নতুন ABI ক্ষেত্র যোগ করার চেয়ে বেশি প্রয়োজন।

    • প্যাচ aosp/1255544 অংশীদার কার্নেল এবং ACK এর মধ্যে ABI পার্থক্য সমাধান করেছে।

    • প্যাচ aosp/1291018 পূর্ববর্তী প্যাচের GKI পরীক্ষার সময় পাওয়া কার্যকরী সমস্যাগুলি সমাধান করেছে৷ একটি একক সেন্সরে একাধিক তাপীয় অঞ্চল নিবন্ধনের জন্য সেন্সর প্যারামিটার কাঠামোর সূচনা অন্তর্ভুক্ত।

  • CONFIG_NL80211_TESTMODE ABI পরিবর্তন ( aosp/1344321 )। এই প্যাচটি ABI-এর জন্য প্রয়োজনীয় কাঠামোগত পরিবর্তনগুলি যোগ করেছে এবং নিশ্চিত করেছে যে অতিরিক্ত ক্ষেত্রগুলি কার্যকরী পার্থক্য সৃষ্টি করে না, অংশীদারদের তাদের উত্পাদন কার্নেলে CONFIG_NL80211_TESTMODE অন্তর্ভুক্ত করতে এবং এখনও GKI সম্মতি বজায় রাখতে সক্ষম করে।

রানটাইমে KMI প্রয়োগ করুন

GKI কার্নেলগুলি TRIM_UNUSED_KSYMS=y এবং UNUSED_KSYMS_WHITELIST=<union of all symbol lists> কনফিগারেশন বিকল্পগুলি ব্যবহার করে, যা রপ্তানিকৃত চিহ্নগুলিকে সীমাবদ্ধ করে (যেমন EXPORT_SYMBOL_GPL() ব্যবহার করে রপ্তানি করা প্রতীকগুলিকে একটি প্রতীক তালিকায় তালিকাভুক্ত করে৷ অন্যান্য সমস্ত প্রতীক অরপ্তানি করা হয় না, এবং একটি অরপ্তানিযোগ্য প্রতীকের প্রয়োজন এমন একটি মডিউল লোড করা অস্বীকার করা হয়৷ এই বিধিনিষেধটি নির্মাণের সময় প্রয়োগ করা হয় এবং অনুপস্থিত এন্ট্রিগুলিকে পতাকাঙ্কিত করা হয়।

উন্নয়নের উদ্দেশ্যে, আপনি একটি GKI কার্নেল বিল্ড ব্যবহার করতে পারেন যাতে প্রতীক ছাঁটাই অন্তর্ভুক্ত নয় (অর্থাৎ সাধারণত রপ্তানি করা সমস্ত প্রতীক ব্যবহার করা যেতে পারে)। এই বিল্ডগুলি সনাক্ত করতে, ci.android.com-kernel_debug_aarch64 বিল্ডগুলি সন্ধান করুন।

মডিউল সংস্করণ ব্যবহার করে KMI প্রয়োগ করুন

জেনেরিক কার্নেল ইমেজ (GKI) কার্নেল মডিউল সংস্করণ ব্যবহার করে ( CONFIG_MODVERSIONS ) রানটাইমে KMI সম্মতি কার্যকর করার জন্য একটি অতিরিক্ত পরিমাপ হিসাবে। মডিউল ভার্সনিং মডিউল লোডের সময় সাইক্লিক রিডানডেন্সি চেক (CRC) অমিল ব্যর্থতার কারণ হতে পারে যদি একটি মডিউলের প্রত্যাশিত KMI vmlinux KMI এর সাথে মেলে না। উদাহরণস্বরূপ, নিম্নোক্তটি একটি সাধারণ ব্যর্থতা যা মডিউল লোডের সময় ঘটে থাকে সিআরসি অমিলের কারণে 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 ''

মডিউল সংস্করণ ব্যবহার

মডিউল সংস্করণ নিম্নলিখিত কারণগুলির জন্য দরকারী:

  • মডিউল ভার্সনিং ডেটা স্ট্রাকচারের দৃশ্যমানতার পরিবর্তনগুলিকে ধরে। যদি মডিউলগুলি অস্বচ্ছ ডেটা স্ট্রাকচার পরিবর্তন করে, অর্থাৎ, ডেটা স্ট্রাকচার যা KMI-এর অংশ নয়, সেগুলি ভবিষ্যত কাঠামোর পরিবর্তনের পরে ভেঙে যায়।

    একটি উদাহরণ হিসাবে, 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-তে একটি অনাবিষ্কৃত অসামঞ্জস্যতার ফলে হতে পারে।

মডিউল সংস্করণ সক্ষম করা এই সমস্ত সমস্যা প্রতিরোধ করে।

ডিভাইস বুট না করেই CRC অমিল আছে কিনা পরীক্ষা করুন

stgdiff অন্যান্য ABI পার্থক্যের সাথে কার্নেলের মধ্যে CRC অমিলের তুলনা করে এবং রিপোর্ট করে।

উপরন্তু, CONFIG_MODVERSIONS সক্ষম সহ একটি সম্পূর্ণ কার্নেল বিল্ড স্বাভাবিক বিল্ড প্রক্রিয়ার অংশ হিসাবে একটি Module.symvers ফাইল তৈরি করে। এই ফাইলটিতে কার্নেল ( vmlinux ) এবং মডিউল দ্বারা রপ্তানি করা প্রতিটি প্রতীকের জন্য একটি লাইন রয়েছে। প্রতিটি লাইনে CRC মান, প্রতীকের নাম, প্রতীকের নামস্থান, vmlinux বা মডিউলের নাম যা প্রতীকটি রপ্তানি করছে এবং রপ্তানির প্রকার (উদাহরণস্বরূপ, EXPORT_SYMBOL বনাম EXPORT_SYMBOL_GPL )।

vmlinux দ্বারা রপ্তানি করা প্রতীকগুলির মধ্যে কোন CRC পার্থক্য পরীক্ষা করার জন্য আপনি GKI বিল্ড এবং আপনার বিল্ডের মধ্যে Module.symvers ফাইলগুলির তুলনা করতে পারেন। vmlinux দ্বারা রপ্তানি করা কোনো প্রতীকে CRC মানের পার্থক্য থাকলে এবং সেই প্রতীকটি আপনার ডিভাইসে আপনার লোড করা মডিউলগুলির একটি দ্বারা ব্যবহৃত হয়, মডিউলটি লোড হয় না।

যদি আপনার কাছে সমস্ত বিল্ড আর্টিফ্যাক্ট না থাকে, কিন্তু আপনার কাছে GKI কার্নেলের vmlinux ফাইল এবং আপনার কার্নেল থাকে, তাহলে আপনি উভয় কার্নেলে নিম্নলিখিত কমান্ডটি চালিয়ে এবং আউটপুট তুলনা করে একটি নির্দিষ্ট প্রতীকের জন্য CRC মান তুলনা করতে পারেন:

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

উদাহরণস্বরূপ, নিম্নলিখিত কমান্ডটি module_layout চিহ্নের জন্য CRC মান পরীক্ষা করে:

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

সিআরসি অমিল সমাধান করুন

একটি মডিউল লোড করার সময় একটি CRC অমিল সমাধান করতে নিম্নলিখিত পদক্ষেপগুলি ব্যবহার করুন:

  1. নিম্নলিখিত কমান্ডে দেখানো হিসাবে --kbuild_symtypes বিকল্পটি ব্যবহার করে GKI কার্নেল এবং আপনার ডিভাইস কার্নেল তৈরি করুন:

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

    এই কমান্ডটি প্রতিটি .o ফাইলের জন্য একটি .symtypes ফাইল তৈরি করে। বিস্তারিত জানার জন্য Kleaf-এ KBUILD_SYMTYPES দেখুন।

    অ্যান্ড্রয়েড 13 এবং নিম্নের জন্য আপনি যে কমান্ডটি কার্নেল তৈরি করতে ব্যবহার করেন তার সামনে KBUILD_SYMTYPES=1 রেখে GKI কার্নেল এবং আপনার ডিভাইস কার্নেল তৈরি করুন, যেমনটি নিম্নলিখিত কমান্ডে দেখানো হয়েছে:

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

    build_abi.sh, KBUILD_SYMTYPES=1 পতাকা ইতিমধ্যেই স্পষ্টভাবে সেট করা আছে।

  2. নিম্নলিখিত কমান্ডটি ব্যবহার করে .c ফাইলটি সন্ধান করুন যেখানে CRC অমিল সহ চিহ্নটি রপ্তানি করা হয়েছে:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
    
  3. .c ফাইলে GKI-তে একটি অনুরূপ .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. দুটি ফাইল তুলনা করুন এবং সমস্ত পার্থক্য ঠিক করুন।

কেস 1: ডেটা টাইপ দৃশ্যমানতার কারণে পার্থক্য

যদি একটি কার্নেল মডিউলগুলিতে একটি চিহ্ন বা ডেটা টাইপ অস্বচ্ছ রাখে এবং অন্য কার্নেল না রাখে, তাহলে দুটি কার্নেলের .symtypes ফাইলের মধ্যে পার্থক্যটি দেখা যায়। একটি কার্নেলের .symtypes ফাইলটিতে একটি প্রতীকের জন্য UNKNOWN এবং অন্য কার্নেলের .symtypes ফাইলটিতে প্রতীক বা ডেটা টাইপের একটি প্রসারিত দৃশ্য রয়েছে।

উদাহরণস্বরূপ, আপনার কার্নেলের include/linux/device.h ফাইলে নিম্নলিখিত লাইন যোগ করলে CRC অমিল হয়, যার মধ্যে একটি হল 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 এর মান থাকে এবং GKI কার্নেলে প্রতীকটির প্রসারিত দৃশ্য থাকে (খুবই অসম্ভাব্য), তাহলে আপনার কার্নেলে সর্বশেষ Android কমন কার্নেলটি মার্জ করুন যাতে আপনি সর্বশেষ GKI কার্নেল বেস ব্যবহার করছেন।

বেশিরভাগ ক্ষেত্রে, GKI কার্নেলের মান UNKNOWN , কিন্তু আপনার কার্নেলের পরিবর্তনের কারণে আপনার কার্নেলে প্রতীকটির অভ্যন্তরীণ বিবরণ রয়েছে। এর কারণ হল আপনার কার্নেলের একটি ফাইল একটি #include যোগ করেছে যা GKI কার্নেলে নেই।

প্রায়শই, সমাধানটি genksyms থেকে নতুন #include লুকানোর মতোই সহজ।

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

অন্যথায়, পার্থক্য সৃষ্টিকারী #include সনাক্ত করতে, এই পদক্ষেপগুলি অনুসরণ করুন:

  1. শিরোনাম ফাইলটি খুলুন যা এই পার্থক্যের সাথে প্রতীক বা ডেটা টাইপ সংজ্ঞায়িত করে। উদাহরণস্বরূপ, struct fwnode_handle এর জন্য include/linux/fwnode.h সম্পাদনা করুন।

  2. হেডার ফাইলের শীর্ষে নিম্নলিখিত কোড যোগ করুন:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. মডিউলের .c ফাইলটিতে একটি CRC অমিল আছে, যে কোনো #include লাইনের আগে প্রথম লাইন হিসেবে নিম্নলিখিতটি যোগ করুন।

    #define CRC_CATCH 1
    
  4. আপনার মডিউল কম্পাইল করুন. ফলস্বরূপ বিল্ড-টাইম ত্রুটি হেডার ফাইল #include এর চেইন দেখায় যা এই CRC অমিলের দিকে পরিচালিত করে। উদাহরণ স্বরূপ:

    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 এ আপলোড করুন এবং এটিকে একত্রিত করুন

কেস 2: ডেটা টাইপ পরিবর্তনের কারণে পার্থক্য

যদি একটি প্রতীক বা ডেটা টাইপের জন্য CRC অমিল দৃশ্যমানতার পার্থক্যের কারণে না হয়, তবে এটি ডেটা টাইপের প্রকৃত পরিবর্তন (সংযোজন, অপসারণ বা পরিবর্তন) এর কারণে হয়।

উদাহরণস্বরূপ, আপনার কার্নেলে নিম্নলিখিত পরিবর্তন করার ফলে অনেকগুলি সিআরসি অমিল হয় কারণ অনেক চিহ্ন পরোক্ষভাবে এই ধরণের পরিবর্তন দ্বারা প্রভাবিত হয়:

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);

একটি CRC অমিল 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 এ আপলোড করুন এবং এটিকে একত্রিত করুন