Android কার্নেলের ইন-কার্নেল ABI-কে স্থিতিশীল করতে, আপনি Android 11 এবং তার পরবর্তী ভার্সনে উপলভ্য অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI) মনিটরিং টুলিং ব্যবহার করতে পারেন। টুলিং, আগে থেকে থাকা কার্নেল বাইনারি (vmlinux+ GKI মডিউল) থেকে ABI উপস্থাপনা
সংগ্রহ করে ও তুলনা করে। এইসব ABI
প্রতিনিধিত্ব হল .stg ফাইল ও প্রতীক তালিকা। যে ইন্টারফেসের
মাধ্যমে উপস্থাপনা একটি ভিউ দেয়, তাকে কার্নেল মডিউল ইন্টারফেস
(KMI) বলা হয়। KMI-তে হওয়া পরিবর্তন ট্র্যাক ও কমানোর জন্য আপনি টুলিং ব্যবহার করতে পারবেন।
ABI মনিটরিং টুলিং
AOSP-তে ডেভেলপ করা হয়েছে
এবং এটি
STG (বা
Android 13 এবং এর আগের যেকোনও ভার্সনে
libabigail) ব্যবহার করে
প্রতিনিধিত্ব জেনারেট ও তুলনা করে।
এই পৃষ্ঠায় টুলিং, ABI রিপ্রেজেন্টেশন সংগ্রহ ও বিশ্লেষণ করার প্রসেস এবং ইন-কার্নেল ABI-কে স্থিতিশীলতা প্রদান করার জন্য এই ধরনের রিপ্রেজেন্টেশনের ব্যবহার বর্ণনা করা হয়েছে। এছাড়াও, এই পৃষ্ঠায় Android কার্নেলে পরিবর্তন কন্ট্রিবিউট করার তথ্য দেওয়া আছে।
প্রক্রিয়া করুন
কার্নেলের ABI বিশ্লেষণ করতে একাধিক ধাপ লাগে, যার বেশিরভাগই অটোমেট করা যায়:
- কার্নেল ও এর ABI উপস্থাপনা তৈরি করুন।
- বিল্ড ও রেফারেন্সের মধ্যে ABI পার্থক্য বিশ্লেষণ করুন।
- ABI উপস্থাপনা আপডেট করুন (প্রয়োজন হলে)।
- সিম্বল লিস্ট নিয়ে কাজ করা।
নিচের নির্দেশাবলী যেকোনও
কার্নেলের জন্য কাজ করে যা আপনি কোনও
সাপোর্ট করা টুলচেন (যেমন, আগে থেকে তৈরি করা Clang টুলচেন) ব্যবহার করে তৈরি করতে পারেন। repo manifests
সব Android সাধারণ কার্নেল ব্রাঞ্চ এবং একাধিক
ডিভাইস-নির্দিষ্ট কার্নেলের জন্য উপলভ্য, এগুলি যাচাই করে যে আপনি
বিশ্লেষণের জন্য কার্নেল ডিস্ট্রিবিউশন তৈরি করার সময় সঠিক টুলচেন ব্যবহার করা হয়েছে।
প্রতীক তালিকা
KMI-তে কার্নেলের সব প্রতীক বা ৩০,০০০-এর বেশি এক্সপোর্ট করা প্রতীকের সবকটি
অন্তর্ভুক্ত থাকে না। পরিবর্তে, ভেন্ডর মডিউল দ্বারা ব্যবহার করা যেতে পারে এমন চিহ্নগুলি
কার্নেল ট্রিতে (Android 15 এবং তার নিচের ভার্সনে gki/{ARCH}/symbols/* বা android/abi_gki_{ARCH}_*)
সর্বজনীনভাবে রক্ষণাবেক্ষণ করা চিহ্ন তালিকার ফাইলগুলির একটি সেটে স্পষ্টভাবে তালিকাভুক্ত করা হয়েছে। সব সিম্বল লিস্ট ফাইলের সব সিম্বলের ইউনিয়ন
KMI সিম্বলের সেটকে স্টেবল হিসেবে বজায় রাখে। একটি উদাহরণ প্রতীক তালিকা ফাইল
হল
gki/aarch64/symbols/db845c,
যা
DragonBoard 845c-এর জন্য প্রয়োজনীয় প্রতীক ঘোষণা করে।
শুধুমাত্র প্রতীক তালিকায় তালিকাভুক্ত প্রতীক এবং সেগুলির সাথে সম্পর্কিত গঠন ও সংজ্ঞাগুলিকে KMI-এর অংশ হিসেবে বিবেচনা করা হয়। আপনার প্রয়োজনীয় প্রতীক না থাকলে, আপনি নিজের প্রতীক তালিকায় পরিবর্তন পোস্ট করতে পারবেন। নতুন ইন্টারফেস সিম্বল লিস্টে যোগ করার পরে এবং KMI বিবরণের অংশ হলে, সেগুলি স্টেবল হিসেবে ম্যানেজ করা হয় এবং ব্রাঞ্চ ফ্রিজ করার পরে সিম্বল লিস্ট থেকে সরানো বা পরিবর্তন করা যাবে না।
প্রতিটি Android Common Kernel (ACK) KMI কার্নেল ব্রাঞ্চের নিজস্ব সিম্বল লিস্টের সেট
আছে। বিভিন্ন KMI কার্নেল
ব্রাঞ্চের মধ্যে ABI স্থিতিশীলতা প্রদান করার কোনও প্রচেষ্টা করা হয় না। যেমন, android12-5.10-এর KMI, android13-5.10-এর KMI-এর থেকে সম্পূর্ণ আলাদা।
কোন ইন্টারফেসের স্থিতিশীলতা
মনিটর করতে হবে তা সীমিত করতে ABI টুল KMI প্রতীক তালিকা ব্যবহার করে। ভেন্ডরদের থেকে আশা করা হয় যে তারা নিজেদের প্রতীক তালিকা জমা দেবেন এবং আপডেট করবেন, যাতে
তারা যে ইন্টারফেসের উপর নির্ভর করেন সেটি ABI মানানসই কিনা তা যাচাই করা যায়। যেমন,
android16-6.12 কার্নেলের জন্য সিম্বল তালিকার তালিকা দেখতে, https://android.googlesource.com/kernel/common/+/refs/heads/android16-6.12/gki/aarch64/symbols দেখুন
প্রতীক তালিকায় সেইসব প্রতীকের উল্লেখ থাকে যেগুলি নির্দিষ্ট ভেন্ডর বা ডিভাইসের জন্য প্রয়োজন বলে জানানো হয়েছে। টুল দ্বারা ব্যবহৃত সম্পূর্ণ তালিকা হল সমস্ত KMI প্রতীক তালিকা ফাইলের মিলন। ABI টুল প্রতিটি প্রতীকের বিবরণ নির্ধারণ করে, যার মধ্যে ফাংশন সিগনেচার ও নেস্টেড ডেটা স্ট্রাকচার অন্তর্ভুক্ত।
KMI ফ্রিজ করা হলে, আগে থেকে থাকা KMI ইন্টারফেসে কোনও পরিবর্তন করা যায় না; এগুলি স্থিতিশীল থাকে। তবে, বর্তমান ABI-এর স্থিতিশীলতার উপর প্রভাব না পড়লে, ভেন্ডররা যেকোনও সময় KMI-তে চিহ্ন যোগ করতে পারেন। KMI প্রতীক তালিকা দ্বারা উদ্ধৃত হওয়ার সাথে সাথেই নতুন যোগ করা প্রতীকগুলি স্থিতিশীল হিসেবে বজায় রাখা হয়। কোনও কার্নেলের তালিকা থেকে প্রতীক সরানো উচিত নয়, যতক্ষণ না এটি নিশ্চিত করা যায় যে কোনও ডিভাইস কখনও সেই প্রতীকের উপর নির্ভর করে শিপ করা হয়নি।
আপনি প্রতীক তালিকা কীভাবে ব্যবহার করবেন থেকে নির্দেশাবলী ব্যবহার করে কোনও ডিভাইসের জন্য KMI প্রতীক তালিকা তৈরি করতে পারেন। অনেক পার্টনার ACK পিছু একটি করে প্রতীক তালিকা জমা দেন, তবে এটি বাধ্যতামূলক নয়। এটি রক্ষণাবেক্ষণে সাহায্য করলে, আপনি একাধিক প্রতীক তালিকা জমা দিতে পারেন।
KMI-এর মেয়াদ বাড়ানো
KMI চিহ্ন ও সংশ্লিষ্ট স্ট্রাকচার স্থিতিশীল (অর্থাৎ, ফ্রোজেন KMI সহ কার্নেলে স্থিতিশীল ইন্টারফেস ভেঙে দেয় এমন পরিবর্তন গ্রহণ করা যাবে না) হিসেবে বজায় রাখা হলেও, GKI কার্নেল এক্সটেনশনের জন্য উন্মুক্ত থাকে, যাতে বছরের শেষের দিকে শিপ করা ডিভাইসগুলিকে KMI ফ্রোজেন হওয়ার আগে তাদের সমস্ত নির্ভরশীলতা নির্ধারণ করতে না হয়। KMI-এর মেয়াদ বাড়াতে, আপনি নতুন বা আগে থেকে এক্সপোর্ট করা কার্নেল ফাংশনের জন্য KMI-তে নতুন চিহ্ন যোগ করতে পারবেন, এমনকি KMI ফ্রিজ করা থাকলেও। নতুন কার্নেল প্যাচগুলিও গ্রহণ করা হতে পারে যদি সেগুলি KMI ভেঙে না দেয়।
KMI ভেঙে যাওয়া সম্পর্কে
কার্নেলের সোর্স থাকে এবং সেই সোর্স থেকে বাইনারি তৈরি করা হয়।
ABI-মনিটর করা কার্নেল ব্রাঞ্চে বর্তমান GKI
ABI-এর ABI উপস্থাপনা (.stg ফাইল হিসেবে) অন্তর্ভুক্ত থাকে। বাইনারি (vmlinux, Image এবং
যেকোনও GKI মডিউল) তৈরি করার পরে, বাইনারি থেকে
ABI রিপ্রেজেন্টেশন এক্সট্র্যাক্ট করা যেতে পারে। কার্নেল সোর্স ফাইলে করা যেকোনও পরিবর্তন বাইনারি ফাইলকে প্রভাবিত করতে পারে এবং এর ফলে এক্সট্র্যাক্ট করা .stg-এর উপরও প্রভাব পড়তে পারে। ABI কমপ্লায়েন্স বিশ্লেষণ, কমিট করা .stg ফাইলের সাথে বিল্ড আর্টিফ্যাক্ট থেকে এক্সট্র্যাক্ট করা ফাইলের তুলনা করে এবং Gerrit-এ পরিবর্তনের ক্ষেত্রে Lint-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 রান করাবেন, তখন টুলিং নন-জিরো এরর কোড সহ বেরিয়ে আসবে এবং এই ধরনের 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-তে পার্থক্য শনাক্ত করা হয়েছে
ভুলের সবচেয়ে সাধারণ কারণ হল, কোনও ড্রাইভার যখন কার্নেল থেকে এমন কোনও নতুন চিহ্ন ব্যবহার করে যা কোনও চিহ্ন তালিকাতে নেই।
আপনার প্রতীক তালিকায় প্রতীকটি অন্তর্ভুক্ত না থাকলে, প্রথমে আপনাকে যাচাই করতে হবে যে
EXPORT_SYMBOL_GPL(symbol_name)-এর সাথে এটি এক্সপোর্ট করা হয়েছে
এবং তারপর প্রতীক তালিকা ও
ABI উপস্থাপনা আপডেট করতে হবে। যেমন, নিম্নলিখিত পরিবর্তনগুলি android-12-5.10 শাখায়
নতুন ইনক্রিমেন্টাল FS ফিচার যোগ করে, যার মধ্যে
প্রতীক তালিকা ও ABI উপস্থাপনা আপডেট করা অন্তর্ভুক্ত।
- ফিচার পরিবর্তনের উদাহরণ aosp/1345659-এ রয়েছে।
- প্রতীকের তালিকার উদাহরণ aosp/1346742-এ আছে।
- ABI উপস্থাপনা পরিবর্তনের উদাহরণ 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 (দেখুন ABI উপস্থাপনা আপডেট করুন) দু'টিতেই KMI প্রতীক তালিকা আপডেট করুন। ACK-তে সিম্বল তালিকা ও ABI উপস্থাপনা আপডেট করার উদাহরণ দেখতে, aosp/1367601 লিঙ্কে দেখুন।
কার্নেল ABI ব্রেক-আপ সংক্রান্ত সমস্যার সমাধান করা
আপনি ABI পরিবর্তন না করার জন্য কোড রিফ্যাক্টর করে ABI বা ABI উপস্থাপনা আপডেট করে কার্নেল ABI ব্রেकेज ম্যানেজ করতে পারবেন। আপনার পরিস্থিতির জন্য সবচেয়ে ভাল পদ্ধতি নির্ধারণ করতে, নিম্নলিখিত চার্ট ব্যবহার করুন।
ছবি ১. ABI ব্রেकेज সংক্রান্ত সমস্যার সমাধান
ABI পরিবর্তন এড়াতে কোড রিফ্যাক্টর করুন
আগে থেকে থাকা ABI পরিবর্তন করা এড়াতে সব রকম চেষ্টা করুন। অনেক ক্ষেত্রে, ABI-তে প্রভাব ফেলে এমন পরিবর্তন সরাতে আপনার কোড রিফ্যাক্টর করতে পারবেন।
স্ট্রাকচার ফিল্ডের পরিবর্তন রিফ্যাক্টর করা। কোনও পরিবর্তন যদি ডিবাগ ফিচারের জন্য ABI-কে মডিফাই করে, তাহলে ফিল্ডের (স্ট্রাক্ট ও সোর্স রেফারেন্সে) চারপাশে
#ifdefযোগ করুন এবং নিশ্চিত করুন যে#ifdef-এর জন্য ব্যবহৃতCONFIGপ্রোডাকশন defconfig ওgki_defconfig-এর জন্য বন্ধ করা আছে। ABI না ভেঙে কীভাবে ডিবাগ কনফিগারেশন স্ট্রাক্টে যোগ করা যায় তার উদাহরণ দেখতে, এই প্যাচসেট দেখুন।মূল কার্নেল পরিবর্তন না করার জন্য ফিচার রিফ্যাক্টর করা। পার্টনার মডিউলকে সাপোর্ট করার জন্য ACK-তে নতুন ফিচার যোগ করতে হলে, পরিবর্তনের ABI পার্টটি রিফ্যাক্টর করার চেষ্টা করুন, যাতে কার্নেল ABI পরিবর্তন করতে না হয়। কার্নেল ABI পরিবর্তন না করে অতিরিক্ত ক্ষমতা যোগ করার জন্য বিদ্যমান কার্নেল ABI ব্যবহার করার উদাহরণ দেখতে aosp/1312213 দেখুন।
Android Gerrit-এ কোনও ভেঙে যাওয়া ABI ঠিক করা
আপনি যদি ইচ্ছাকৃতভাবে কার্নেল ABI না ভেঙে থাকেন, তাহলে আপনাকে ABI মনিটরিং টুলিং দ্বারা প্রদত্ত নির্দেশিকা ব্যবহার করে, তদন্ত করতে হবে। ডেটা স্ট্রাকচার ও সংশ্লিষ্ট সিম্বল CRC পরিবর্তন অথবা কনফিগারেশন বিকল্পে পরিবর্তন যা উপরে উল্লিখিত কারণগুলির মধ্যে কোনও একটির দিকে নিয়ে যায়, এগুলি হল ব্রেकेज হওয়ার সবচেয়ে সাধারণ কারণ। টুলটি যেসব সমস্যা খুঁজে পেয়েছে, সেগুলি সমাধান করার মাধ্যমে শুরু করুন।
আপনি স্থানীয়ভাবে ABI ফাইন্ডিং আবার তৈরি করতে পারবেন, কার্নেল ও তার ABI রিপ্রেজেন্টেশন তৈরি করুন দেখুন।
Lint-1 লেবেল সম্পর্কে
আপনি যদি ফ্রোজেন বা চূড়ান্ত করা KMI সহ কোনও ব্রাঞ্চে পরিবর্তন আপলোড করেন, তাহলে ABI রিপ্রেজেন্টেশনে করা পরিবর্তনগুলি যাতে প্রকৃত ABI-কে প্রতিফলিত করে এবং কোনও অসামঞ্জস্য (প্রতীক সরানো বা ধরন পরিবর্তন) না থাকে তা নিশ্চিত করতে পরিবর্তনগুলিকে অবশ্যই ABI কমপ্লায়েন্স এবং কম্প্যাটিবিলিটি বিশ্লেষণ পাস করতে হবে।
এইসব ABI বিশ্লেষণের প্রতিটি Lint-1 লেবেল সেট করতে পারে এবং সব সমস্যার সমাধান না হওয়া বা লেবেল ওভাররাইড না করা পর্যন্ত পরিবর্তন জমা দেওয়া ব্লক করতে পারে।
কার্নেল ABI আপডেট করা
ABI পরিবর্তন করা এড়ানো না গেলে, আপনাকে অবশ্যই ACK-তে আপনার কোড পরিবর্তন, ABI উপস্থাপনা এবং প্রতীক তালিকা প্রয়োগ করতে হবে। -1 সরাতে এবং GKI কম্প্যাটিবিলিটি না ভাঙতে Lint পেতে, এইসব ধাপ অনুসরণ করুন:
প্যাচসেটের জন্য Code-Review +2 না পাওয়া পর্যন্ত অপেক্ষা করুন।
আপনার কোড পরিবর্তন ও ABI আপডেট পরিবর্তন মার্জ করুন।
ACK-তে ABI কোড পরিবর্তন আপলোড করা
ACK ABI আপডেট করা নির্ভর করে কী ধরনের পরিবর্তন করা হচ্ছে তার উপর।
ABI পরিবর্তন যদি এমন কোনও ফিচারের সাথে সম্পর্কিত হয় যা CTS বা VTS টেস্টকে প্রভাবিত করে, তাহলে পরিবর্তনটি সাধারণত ACK-তে যেমন আছে তেমনভাবে চেরি-পিক করা যেতে পারে। যেমন:
- অডিও কাজ করার জন্য aosp/1289677 প্রয়োজন।
- USB কাজ করার জন্য aosp/1295945 প্রয়োজন।
যদি কোনও ABI পরিবর্তন এমন কোনও ফিচারের জন্য হয় যা ACK-এর সাথে শেয়ার করা যেতে পারে, তাহলে সেই পরিবর্তনটি ACK-তে যেমন আছে তেমনই চেরি-পিক করা যেতে পারে। উদাহরণস্বরূপ, নিম্নলিখিত পরিবর্তনগুলি CTS বা VTS পরীক্ষার জন্য প্রয়োজন নেই তবে ACK-এর সাথে শেয়ার করা যেতে পারে:
- aosp/1250412 হল থার্মাল ফিচার সংক্রান্ত পরিবর্তন।
- aosp/1288857
হল একটি
EXPORT_SYMBOL_GPLপরিবর্তন।
ABI পরিবর্তন যদি এমন কোনও নতুন ফিচার নিয়ে আসে যা ACK-তে অন্তর্ভুক্ত করার প্রয়োজন নেই, তাহলে আপনি নিম্নলিখিত বিভাগে বর্ণনা করা স্টাব ব্যবহার করে ACK-তে সিম্বল নিয়ে আসতে পারেন।
ACK-এর জন্য স্টাব ব্যবহার করা
স্টাব শুধুমাত্র মূল কার্নেল পরিবর্তনের জন্য প্রয়োজনীয় যা পারফর্ম্যান্স এবং পাওয়ার পরিবর্তনের মতো ACK-এর উপকার করে না। নিচের তালিকায় GKI-এর জন্য ACK-তে স্টাব ও আংশিক চেরি-পিকের উদাহরণ দেওয়া আছে।
Core-isolate ফিচার স্টাব (aosp/1284493). ACK-এর ক্ষমতা প্রয়োজনীয় নয়, তবে আপনার মডিউলকে এইসব চিহ্ন ব্যবহার করতে হলে ACK-তে চিহ্নগুলি থাকতে হবে ।
ভেন্ডর মডিউলের জন্য প্লেসহোল্ডার চিহ্ন (aosp/1288860)।
প্রতি-প্রসেস
mmইভেন্ট ট্র্যাকিং ফিচারের শুধুমাত্র ABI-এর জন্য বেছে নেওয়া হয়েছে(aosp/1288454)। ACK-এর জন্য মূল প্যাচটি বেছে নেওয়া হয়েছে এবং তারপরtask_structওmm_event_count-এর জন্য ABI ডিফারেন্স সমাধান করতে শুধুমাত্র প্রয়োজনীয় পরিবর্তনগুলি অন্তর্ভুক্ত করার জন্য সেটি ট্রিম করা হয়েছে। এই প্যাচটিmm_event_typeenum-কেও আপডেট করে যাতে ফাইনাল মেম্বার থাকে।থার্মাল স্ট্রাক ABI পরিবর্তনের আংশিক চেরি-পিকিং যার জন্য নতুন ABI ফিল্ড যোগ করার চেয়ে বেশি কিছু প্রয়োজন।
প্যাচ aosp/1255544 পার্টনার কার্নেল ও ACK-এর মধ্যে ABI সংক্রান্ত পার্থক্য সমাধান করেছে।
প্যাচ aosp/1291018 আগের প্যাচের GKI টেস্টিংয়ের সময় খুঁজে পাওয়া ফাংশনাল সমস্যার সমাধান করেছে। একটি সেন্সরে একাধিক থার্মাল জোন রেজিস্টার করার জন্য সেন্সর প্যারামিটার স্ট্রাক্ট ইনিশিয়ালাইজ করার মাধ্যমে সমস্যার সমাধান করা হয়েছে।
CONFIG_NL80211_TESTMODEABI পরিবর্তন (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) কার্নেল রানটাইমে KMI সম্মতি এনফোর্স করার জন্য অতিরিক্ত ব্যবস্থা হিসেবে মডিউল ভার্সনিং
(CONFIG_MODVERSIONS) ব্যবহার করে। মডিউল ভার্সনিংয়ের কারণে মডিউল লোড করার সময় সাইক্লিক রিডান্ডেন্সি চেক (CRC) সংক্রান্ত সমস্যা হতে পারে
যদি কোনও মডিউলের প্রত্যাশিত KMI,
vmlinux KMI-এর সাথে না মেলে। যেমন, নিম্নলিখিত সমস্যাটি হল একটি সাধারণ সমস্যা যা module_layout() প্রতীকের CRC না মেলাতে পারার কারণে
মডিউল লোড করার সময় ঘটে:
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-মানানসই নয়। এই চেক, KMI-তে শনাক্ত করা যায়নি এমন ইনকম্প্যাটিবিলিটির কারণে হতে পারে এমন কঠিন-টু-ডিবাগ রানটাইম সমস্যা এবং কার্নেল ক্র্যাশ প্রতিরোধ করে।
মডিউল ভার্সনিং চালু করলে এইসব সমস্যা এড়ানো যায়।
ডিভাইস বুট না করেই CRC অমিল চেক করুন
stgdiff অন্যান্য
ABI পার্থক্য সহ কার্নেলগুলির মধ্যে CRC অমিল তুলনা করে রিপোর্ট করে।
এছাড়াও, CONFIG_MODVERSIONS চালু থাকা অবস্থায় সম্পূর্ণ কার্নেল বিল্ড করলে, সাধারণ বিল্ড প্রসেসের অংশ হিসেবে একটি
Module.symvers ফাইল তৈরি হয়। এই ফাইলে কার্নেল (vmlinux) ও মডিউল দ্বারা এক্সপোর্ট করা প্রতিটি প্রতীকের জন্য একটি করে
লাইন থাকে। প্রতিটি
লাইনে CRC ভ্যালু, সিম্বলের নাম, সিম্বল নেমস্পেস, vmlinux বা
মডিউলের নাম যা সিম্বল এক্সপোর্ট করছে এবং এক্সপোর্ট করার ধরন (যেমন,
EXPORT_SYMBOL বনাম EXPORT_SYMBOL_GPL) থাকে।
GKI বিল্ড ও আপনার বিল্ডের মধ্যে Module.symvers ফাইল তুলনা করে
vmlinux-এর এক্সপোর্ট করা প্রতীকে কোনও CRC পার্থক্য আছে কিনা তা চেক করতে পারবেন। 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_layoutCRC সংক্রান্ত অমিল সমাধান করা
কোনও মডিউল লোড করার সময় CRC অমিল সংক্রান্ত সমস্যার সমাধান করতে নিম্নলিখিত ধাপগুলি অনুসরণ করুন:
নিম্নলিখিত কমান্ডে দেখানো
--kbuild_symtypesবিকল্প ব্যবহার করে GKI কার্নেল এবং আপনার ডিভাইস কার্নেল তৈরি করুন:tools/bazel run --kbuild_symtypes //common:kernel_aarch64_distএই কমান্ড প্রতিটি
.oফাইলের জন্য একটি করে.symtypesফাইল তৈরি করে। বিবরণের জন্যKBUILD_SYMTYPESKleaf-এ দেখুন ।Android 13 ও এর আগের যেকোনও ভার্সনের জন্য GKI কার্নেল ও আপনার ডিভাইস কার্নেল তৈরি করতে, কার্নেল তৈরি করার জন্য আপনি যে কমান্ড ব্যবহার করেন তার আগে
KBUILD_SYMTYPES=1যোগ করুন, যেমনটি নিম্নলিখিত কমান্ডে দেখানো হয়েছে:KBUILD_SYMTYPES=1 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.shbuild_abi.sh,ব্যবহার করার সময়,KBUILD_SYMTYPES=1ফ্ল্যাগ আগে থেকেই অন্তর্নিহিতভাবে সেট করা থাকে ।CRC না মেলা চিহ্নটি যে
.cফাইলে এক্সপোর্ট করা হয়েছে সেটি খুঁজে পেতে নিম্নলিখিত কমান্ড ব্যবহার করুন:git -C common grep EXPORT_SYMBOL.*module_layout kernel/module/version.c:EXPORT_SYMBOL(module_layout);.cফাইলের সাথে GKI-তে সংশ্লিষ্ট.symtypesফাইল এবং আপনার ডিভাইস কার্নেল বিল্ড আর্টিফ্যাক্ট আছে। নিচের কমান্ড ব্যবহার করে.symtypesফাইলটি খুঁজে বের করুন:cd bazel-bin/common/kernel_aarch64/symtypes ls -1 kernel/module/version.symtypesAndroid 13 ও তার আগের যেকোনও ভার্সনে, লিগ্যাসি বিল্ড স্ক্রিপ্ট ব্যবহার করলে, লোকেশন
out/$BRANCH/commonঅথবাout_abi/$BRANCH/commonহতে পারে।প্রতিটি
.symtypesফাইল হল একটি প্লেন টেক্সট ফাইল যাতে ধরন ও চিহ্নের বিবরণ থাকে:প্রতিটি লাইন
key descriptionফর্মের হয় যেখানে বিবরণ একই ফাইলের অন্যান্য কী উল্লেখ করতে পারে।[s|u|e|t]#foo-এর মতো কী[struct|union|enum|typedef] foo-কে রেফার করে। যেমন:t#bool typedef _Bool boolx#উপসর্গ নেই এমন কীগুলি হল শুধুমাত্র প্রতীকের নাম। যেমন:find_module s#module * find_module ( const char * )
দুটি ফাইলের মধ্যে তুলনা করে সব পার্থক্য সমাধান করুন।
সমস্যাজনক পরিবর্তনের ঠিক আগে এবং তারপরে সমস্যাজনক পরিবর্তনের সময় বিল্ডের সাথে symtypes জেনারেট করা সবচেয়ে ভালো। সব ফাইল সেভ করার অর্থ হল, সেগুলি
একসাথে তুলনা করা যাবে।
যেমন,
diff -r -N -U0 good badঅন্যথায়, শুধু আগ্রহের নির্দিষ্ট ফাইলগুলি তুলনা করুন।
কেস ১: ডেটার ধরন সংক্রান্ত দৃশ্যমানতার কারণে পার্থক্য
নতুন #include সোর্স ফাইলে নতুন ধরনের সংজ্ঞা (যেমন struct foo) আনতে পারে।
এইসব ক্ষেত্রে, সংশ্লিষ্ট .symtypes ফাইলে এর বিবরণ
খালি structure_type foo { } থেকে সম্পূর্ণ সংজ্ঞায় পরিবর্তিত হবে।
এর ফলে .symtypes ফাইলের সব প্রতীকের CRC প্রভাবিত হবে, যেগুলির
বিবরণ সরাসরি বা পরোক্ষভাবে টাইপ ডেফিনিশনের উপর নির্ভর করে।
যেমন, আপনার কার্নেলে
include/linux/device.h ফাইলে নিম্নলিখিত লাইন যোগ করলে CRC ম্যাচ না করার সমস্যা হয়, যার মধ্যে একটি
module_layout()-এর জন্য হয়:
#include <linux/fwnode.h>
সেই চিহ্নের জন্য module/version.symtypes তুলনা করলে, নিম্নলিখিত পার্থক্যগুলি
প্রকাশ পায়:
$ diff -u <GKI>/kernel/module/version.symtypes <your kernel>/kernel/module/version.symtypes
--- <GKI>/kernel/module/version.symtypes
+++ <your kernel>/kernel/module/version.symtypes
@@ -334,12 +334,15 @@
...
-s#fwnode_handle structure_type fwnode_handle { }
+s#fwnode_reference_args structure_type fwnode_reference_args { s#fwnode_handle * fwnode ; unsigned int nargs ; t#u64 args [ 8 ] ; }
...
GKI কার্নেলে সম্পূর্ণ টাইপ ডেফিনেশন থাকলে, কিন্তু আপনার কার্নেলে সেটি না থাকলে (খুবই বিরল), তাহলে আপনার কার্নেলে লেটেস্ট Android Common Kernel মার্জ করুন যাতে আপনি লেটেস্ট GKI কার্নেল বেস ব্যবহার করতে পারেন।
অধিকাংশ ক্ষেত্রে, GKI কার্নেলে .symtypes-এ সম্পূর্ণ টাইপ ডেফিনেশন থাকে না, কিন্তু অতিরিক্ত #include ডিরেক্টিভের কারণে আপনার কার্নেলে এটি থাকে।
Android 16 ও তার পরবর্তী যেকোনও ভার্সনের জন্য রেজোলিউশন
প্রভাবিত সোর্স ফাইলে Android KABI স্ট্যাবিলাইজেশন হেডার অন্তর্ভুক্ত আছে কিনা তা নিশ্চিত করুন:
#include <linux/android_kabi.h>
প্রভাবিত প্রতিটি ধরনের জন্য, প্রভাবিত সোর্স ফাইলে
গ্লোবাল স্কোপে ANDROID_KABI_DECLONLY(name); যোগ করুন।
যেমন, symtypes ডিফারেন্স যদি এটি হয়:
--- good/drivers/android/vendor_hooks.symtypes
+++ bad/drivers/android/vendor_hooks.symtypes
@@ -1051 +1051,2 @@
-s#ubuf_info structure_type ubuf_info { }
+s#ubuf_info structure_type ubuf_info { member pointer_type { const_type { s#ubuf_info_ops } } ops data_member_location(0) , member t#refcount_t refcnt data_member_location(8) , member t#u8 flags data_member_location(12) } byte_size(16)
+s#ubuf_info_ops structure_type ubuf_info_ops { member pointer_type { subroutine_type ( formal_parameter pointer_type { s#sk_buff } , formal_parameter pointer_type { s#ubuf_info } , formal_parameter t#bool ) -> base_type void } complete data_member_location(0) , member pointer_type { subroutine_type ( formal_parameter pointer_type { s#sk_buff } , formal_parameter pointer_type { s#ubuf_info } ) -> base_type int byte_size(4) encoding(5) } link_skb data_member_location(8) } byte_size(16)
তাহলে সমস্যা হল, struct ubuf_info-এর এখন
symtypes-এ সম্পূর্ণ সংজ্ঞা আছে। এর সমাধান হল drivers/android/vendor_hooks.c-এ একটি লাইন যোগ করা:
ANDROID_KABI_DECLONLY(ubuf_info);
এটি gendwarfksyms-কে নির্দেশ দেয় যাতে ফাইলে নাম দেওয়া ধরনকে অনির্ধারিত হিসেবে বিবেচনা করা হয়।
আরও জটিল সম্ভাবনা হল যে নতুন #include নিজেই একটি হেডার
ফাইলে রয়েছে। এই ক্ষেত্রে, আপনাকে সোর্স ফাইল জুড়ে
ANDROID_KABI_DECLONLY ম্যাক্রো ইনভোকেশন-এর বিভিন্ন সেট ডিস্ট্রিবিউট করতে হতে পারে যা পরোক্ষভাবে
অতিরিক্ত টাইপ ডেফিনিশন পুল করে কারণ সেগুলির মধ্যে কিছুতে ইতিমধ্যেই কিছু
টাইপ ডেফিনিশন থাকতে পারে।
সহজে পড়ার জন্য, সোর্স ফাইলের শুরুতে এই ধরনের ম্যাক্রো ইনভোকেশন রাখুন।
Android 15 ও এর আগের যেকোনও ভার্সনের জন্য রেজোলিউশন
প্রায়ই, genksyms থেকে নতুন #include লুকিয়ে রাখলেই সমস্যার সমাধান হয়ে যায়।
#ifndef __GENKSYMS__
#include <linux/fwnode.h>
#endif
অন্যথায়, পার্থক্যের কারণ হওয়া #include শনাক্ত করতে, এইসব
ধাপ অনুসরণ করুন:
যে হেডার ফাইলে এই পার্থক্য সহ প্রতীক বা ডেটার ধরন সংজ্ঞায়িত করা হয়েছে সেটি খুলুন। যেমন,
struct fwnode_handle-এর জন্যinclude/linux/fwnode.hএডিট করুন।হেডার ফাইলের সবচেয়ে উপরে নিম্নলিখিত কোড যোগ করুন:
#ifdef CRC_CATCH #error "Included from here" #endifমডিউলের
.cফাইলে CRC অমিল থাকলে,#includeলাইনের আগে প্রথম লাইন হিসেবে নিম্নলিখিতটি যোগ করুন।#define CRC_CATCH 1আপনার মডিউল কম্পাইল করুন। এর ফলে বিল্ড-টাইম সমস্যা দেখা দেয় এবং হেডার ফাইলের
#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 কার্নেলে নেই।
কেস ২: ডেটার ধরনের পরিবর্তনের কারণে পার্থক্য
কোনও প্রতীক বা ডেটার ধরনের CRC না মিললে, তা যদি দৃশ্যমানতার পার্থক্যের কারণে না হয়, তাহলে তা ডেটার ধরনের মধ্যে হওয়া প্রকৃত পরিবর্তনের (যোগ করা, সরানো বা পরিবর্তন করা) কারণে হয়।
যেমন, আপনার কার্নেলে নিম্নলিখিত পরিবর্তন করলে, অনেক প্রতীকে পরোক্ষভাবে এই ধরনের পরিবর্তনের প্রভাব পড়ায়, একাধিক 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 structure_type 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 structure_type 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>পরিবর্তন বা মুছে দেওয়া অংশটি খুঁজে পেতে, ফিরে আসা কমিটের তালিকা পর্যালোচনা করুন। প্রথম কমিটটি সম্ভবত আপনি খুঁজছেন। সেটি না হলে, কমিটটি খুঁজে না পাওয়া পর্যন্ত তালিকাটি দেখুন।
কমিট শনাক্ত করার পরে, আপনার কার্নেলে এটি আগের অবস্থায় ফিরিয়ে আনুন অথবা CRC পরিবর্তনকে আড়াল করতে এটি আপডেট করুন এবং ACK-তে আপলোড করে এটি মার্জ করুন। প্রতিটি অবশিষ্ট ABI ব্রেক নিরাপত্তা সংক্রান্ত কারণে পর্যালোচনা করতে হবে এবং প্রয়োজন হলে অনুমোদিত ব্রেক রেকর্ড করা যেতে পারে।
আগে থেকে থাকা প্যাডিং ব্যবহার করতে চাই
GKI-তে কিছু স্ট্রাকচার প্যাড করা হয় যাতে আগে থেকে থাকা ভেন্ডর মডিউল ভেঙে না দিয়ে সেগুলিকে এক্সটেন্ড করা যায়। আপস্ট্রিম কমিট (যেমন) যদি এই ধরনের স্ট্রাকচারে কোনও মেম্বার যোগ করে, তাহলে প্যাডিংয়ের কিছু অংশ ব্যবহার করার জন্য এটি পরিবর্তন করা যেতে পারে। এই পরিবর্তনটি CRC গণনা থেকে লুকানো হয়।
স্ট্যান্ডার্ডাইজড, সেল্ফ-ডকুমেন্টিং ম্যাক্রো ANDROID_KABI_RESERVE u64
মূল্যের (অ্যালাইন করা) স্পেস রিজার্ভ করে। এটি কোনও মেম্বার ঘোষণার পরিবর্তে ব্যবহার করা হয়।
যেমন:
struct data {
u64 handle;
ANDROID_KABI_RESERVE(1);
ANDROID_KABI_RESERVE(2);
};
ANDROID_KABI_USE
(বা ANDROID_KABI_USE2 বা অন্যান্য ভেরিয়েন্ট যা হয়ত সংজ্ঞায়িত করা হয়েছে) ব্যবহার করে প্রতীক CRC-তে প্রভাব না ফেলেই প্যাডিং ব্যবহার করা যেতে পারে।
মেম্বার sekret এমনভাবে উপলভ্য থাকে যেন এটি সরাসরি ঘোষণা করা হয়েছে, কিন্তু ম্যাক্রোটি
আসলে sekret সহ একটি বেনামী ইউনিয়ন মেম্বার হিসেবে প্রসারিত হয় এবং
gendwarfksyms-এর দ্বারা symtype স্থিতিশীলতা বজায় রাখার জন্য ব্যবহৃত জিনিসও থাকে।
struct data {
u64 handle;
ANDROID_KABI_USE(1, void *sekret);
ANDROID_KABI_RESERVE(2);
};
Android 16 ও তার পরবর্তী যেকোনও ভার্সনের জন্য রেজোলিউশন
gendwarfksyms-এর মাধ্যমে CRC গণনা করা হয় যা DWARF ডিবাগিং ইনফরমেশন ব্যবহার করে,
তাই C ও Rust, দুই ধরনের ক্ষেত্রেই এটি কাজ করে। পরিবর্তনের ধরনের উপর নির্ভর করে রেজোলিউশন
আলাদা আলাদা হয়। কয়েকটি উদাহরণ দেখুন।
নতুন বা পরিবর্তিত এনিউমারেটর
কখনও কখনও নতুন এনিউমেরেটর যোগ করা হয় এবং মাঝে মাঝে MAX বা একই ধরনের
এনিউমেরেটর ভ্যালুও প্রভাবিত হয়। এইসব পরিবর্তন নিরাপদ যদি সেগুলি GKI "এড়িয়ে"
না যায় অথবা আমরা যদি নিশ্চিত হতে পারি যে ভেন্ডর মডিউল তাদের ভ্যালু নিয়ে চিন্তা করে না।
যেমন:
enum outcome {
SUCCESS,
FAILURE,
RETRY,
+ TRY_HARDER,
OUTCOME_LIMIT
};
TRY_HARDER যোগ করা এবং OUTCOME_LIMIT-এ পরিবর্তন করা গ্লোবাল স্কোপে ম্যাক্রো ইনভোকেশন সহ CRC গণনা থেকে লুকানো যেতে পারে:
ANDROID_KABI_ENUMERATOR_IGNORE(outcome, TRY_HARDER);
ANDROID_KABI_ENUMERATOR_VALUE(outcome, OUTCOME_LIMIT, 3);
পড়ার সুবিধার জন্য, এগুলি ঠিক enum সংজ্ঞার পরে রাখুন।
আগে থেকে থাকা গর্তে নতুন স্ট্রাকচার মেম্বার
অ্যালাইনমেন্টের কারণে, urgent এবং scratch-এর মধ্যে অব্যবহৃত বাইট থাকবে।
void *data;
bool urgent;
+ bool retry;
void *scratch;
retry যোগ করার ফলে কোনও বিদ্যমান মেম্বার অফসেট বা স্ট্রাকচারের সাইজ প্রভাবিত হয় না। তবে, এটি প্রতীক CRC বা ABI
প্রতিনিধিত্ব বা দু'টিকেই প্রভাবিত করতে পারে।
এটি CRC গণনা থেকে এটি লুকাবে:
void *data;
bool urgent;
+ ANDROID_KABI_IGNORE(1, bool retry);
void *scratch_space;
মেম্বার retry এমনভাবে উপলভ্য থাকে যেন এটি সরাসরি ঘোষণা করা হয়েছে, কিন্তু ম্যাক্রোটি
আসলে retry সহ একটি বেনামী ইউনিয়ন মেম্বার হিসেবে প্রসারিত হয় এবং
gendwarfksyms-এর দ্বারা symtype স্থিতিশীলতা বজায় রাখার জন্য ব্যবহৃত জিনিসও থাকে।
নতুন মেম্বারদের সাথে স্ট্রাকচারের এক্সটেনশন
কখনও কখনও স্ট্রাকচারের শেষে মেম্বারদের যোগ করা হয়। এর ফলে আগে থেকে থাকা মেম্বারদের অফসেট বা স্ট্রাকচারের আগে থেকে থাকা ব্যবহারকারীদের উপর কোনও প্রভাব পড়ে না, যারা শুধুমাত্র পয়েন্টারের মাধ্যমে এটি অ্যাক্সেস করেন। স্ট্রাকচারের সাইজ এর CRC-কে প্রভাবিত করে এবং এতে পরিবর্তন করা যায়। গ্লোবাল স্কোপে অতিরিক্ত ম্যাক্রো ইনভোকেশন দিয়ে এটি দমন করা যায়, যেমন নিচে দেখানো হয়েছে:
struct data {
u64 handle;
u64 counter;
ANDROID_KABI_IGNORE(1, void *sekret);
};
ANDROID_KABI_BYTE_SIZE(data, 16);
পাঠযোগ্যতার জন্য, এটি struct সংজ্ঞার ঠিক পরেই রাখুন।
কোনও ধরনের বা প্রতীকের ধরনের মধ্যে করা অন্যান্য সব পরিবর্তন
খুব কমই এমন পরিবর্তন হতে পারে যা আগের ক্যাটাগরির মধ্যে পড়ে না, এর ফলে CRC-তে এমন পরিবর্তন হয় যা আগের ম্যাক্রো ব্যবহার করে দমন করা যায় না।
এইসব ক্ষেত্রে, symtypes কোনও ধরন বা প্রতীকের আসল বিবরণ
গ্লোবাল স্কোপে ANDROID_KABI_TYPE_STRING-এর ইনভোকেশন সহ সাপ্লাই করা যেতে পারে।
struct data {
/* extensive changes */
};
ANDROID_KABI_TYPE_STRING("s#data", "original s#data symtypes definition");
পাঠযোগ্যতার জন্য, এটি টাইপ বা প্রতীকের সংজ্ঞা দেওয়ার ঠিক পরেই রাখুন।
Android 15 ও এর আগের যেকোনও ভার্সনের জন্য রেজোলিউশন
genksyms থেকে টাইপ ও প্রতীক টাইপের পরিবর্তন লুকানো প্রয়োজন। __GENKSYMS__-এর মাধ্যমে
প্রিপ্রসেসিং কন্ট্রোল করে এটি করা যেতে পারে।
এইভাবে, ইচ্ছামতো কোড ট্রান্সফর্মেশন প্রকাশ করা যেতে পারে।
যেমন, আগে থেকে থাকা স্ট্রাকচারে কোনও ফাঁকা জায়গা পূরণ করা নতুন মেম্বারকে আড়াল করতে:
struct parcel {
void *data;
bool urgent;
#ifndef __GENKSYMS__
bool retry;
#endif
void *scratch_space;
};