অ্যান্ড্রয়েড কার্নেলের ইন-কার্নেল ABI স্থিতিশীল করতে আপনি Android 11 এবং উচ্চতর সংস্করণে উপলব্ধ অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI) মনিটরিং টুলিং ব্যবহার করতে পারেন। টুলিং বিদ্যমান কার্নেল বাইনারি ( vmlinux
+ GKI মডিউল) থেকে ABI উপস্থাপনা সংগ্রহ ও তুলনা করে। এই ABI উপস্থাপনা হল .stg
ফাইল এবং প্রতীক তালিকা। যে ইন্টারফেসটিতে উপস্থাপনা একটি দৃশ্য দেয় তাকে কার্নেল মডিউল ইন্টারফেস (KMI) বলা হয়। আপনি KMI-তে পরিবর্তনগুলি ট্র্যাক করতে এবং হ্রাস করতে টুলিং ব্যবহার করতে পারেন।
ABI মনিটরিং টুলিং AOSP-তে তৈরি করা হয়েছে এবং উপস্থাপনা তৈরি করতে এবং তুলনা করতে STG (বা Android 13 এবং তার থেকে কম সময়ে libabigail
) ব্যবহার করে।
এই পৃষ্ঠাটি টুলিং, ABI উপস্থাপনা সংগ্রহ ও বিশ্লেষণের প্রক্রিয়া এবং ইন-কারনেল ABI-কে স্থিতিশীলতা প্রদানের জন্য এই জাতীয় উপস্থাপনাগুলির ব্যবহার বর্ণনা করে। এই পৃষ্ঠাটি অ্যান্ড্রয়েড কার্নেলগুলিতে অবদান রাখার জন্য তথ্য সরবরাহ করে।
প্রক্রিয়া
কার্নেলের ABI বিশ্লেষণ একাধিক পদক্ষেপ নেয়, যার বেশিরভাগই স্বয়ংক্রিয় হতে পারে:
- কার্নেল এবং এর ABI উপস্থাপনা তৈরি করুন ।
- বিল্ড এবং একটি রেফারেন্সের মধ্যে ABI পার্থক্য বিশ্লেষণ করুন ।
- ABI প্রতিনিধিত্ব আপডেট করুন (যদি প্রয়োজন হয়) ।
- প্রতীক তালিকা নিয়ে কাজ করুন ।
নিম্নলিখিত নির্দেশাবলী যেকোন কার্নেলের জন্য কাজ করে যা আপনি একটি সমর্থিত টুলচেন ব্যবহার করে তৈরি করতে পারেন (যেমন প্রি-বিল্ট ক্ল্যাং টুলচেন)। repo manifests
সমস্ত অ্যান্ড্রয়েড সাধারণ কার্নেল শাখার জন্য এবং বেশ কয়েকটি ডিভাইস-নির্দিষ্ট কার্নেলের জন্য উপলব্ধ, তারা নিশ্চিত করে যে আপনি বিশ্লেষণের জন্য একটি কার্নেল বিতরণ তৈরি করার সময় সঠিক টুলচেইন ব্যবহার করা হয়েছে।
প্রতীক তালিকা
KMI কার্নেলের সমস্ত চিহ্ন বা এমনকি 30,000+ রপ্তানি করা চিহ্নগুলির মধ্যেও অন্তর্ভুক্ত করে না। পরিবর্তে, বিক্রেতা মডিউলগুলি দ্বারা ব্যবহার করা যেতে পারে এমন চিহ্নগুলি স্পষ্টভাবে কার্নেল ট্রিতে ( gki/{ARCH}/symbols/*
বা android/abi_gki_{ARCH}_*
Android 15 এবং তার নীচের অংশে) রক্ষণাবেক্ষণ করা প্রতীক তালিকা ফাইলগুলির একটি সেটে তালিকাভুক্ত করা হয়েছে। সমস্ত প্রতীক তালিকা ফাইলের সমস্ত প্রতীকের মিলন স্থিতিশীল হিসাবে বজায় রাখা KMI প্রতীকগুলির সেটকে সংজ্ঞায়িত করে। একটি উদাহরণ প্রতীক তালিকা ফাইল হল gki/aarch64/symbols/db845c
, যা ড্রাগনবোর্ড 845c-এর জন্য প্রয়োজনীয় চিহ্নগুলি ঘোষণা করে।
শুধুমাত্র একটি প্রতীক তালিকায় তালিকাভুক্ত চিহ্নগুলি এবং তাদের সম্পর্কিত কাঠামো এবং সংজ্ঞাগুলি কেএমআই-এর অংশ হিসাবে বিবেচনা করা হয়। আপনার প্রয়োজনীয় প্রতীক উপস্থিত না থাকলে আপনি আপনার প্রতীক তালিকায় পরিবর্তন পোস্ট করতে পারেন। নতুন ইন্টারফেসগুলি একটি প্রতীক তালিকায় থাকার পরে এবং KMI বর্ণনার অংশ হওয়ার পরে, সেগুলিকে স্থিতিশীল হিসাবে বজায় রাখা হয় এবং শাখাটি হিমায়িত হওয়ার পরে প্রতীক তালিকা থেকে সরানো বা সংশোধন করা উচিত নয়৷
প্রতিটি অ্যান্ড্রয়েড কমন কার্নেল (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 প্রতীক তালিকা ফাইলগুলির সমস্ত মিলন। এবিআই টুলস ফাংশন সিগনেচার এবং নেস্টেড ডেটা স্ট্রাকচার সহ প্রতিটি চিহ্নের বিবরণ নির্ধারণ করে।
যখন 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 পার্থক্য সনাক্ত করা হয়েছে
ত্রুটির সবচেয়ে সাধারণ কারণ হল যখন একজন ড্রাইভার কার্নেল থেকে একটি নতুন প্রতীক ব্যবহার করে যা প্রতীক তালিকার কোনোটিতে নেই।
যদি প্রতীকটি আপনার প্রতীক তালিকায় অন্তর্ভুক্ত না থাকে, তাহলে আপনাকে প্রথমে যাচাই করতে হবে যে এটি 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 উভয় ক্ষেত্রেই KMI প্রতীক তালিকা আপডেট করুন (দেখুন ABI প্রতিনিধিত্ব আপডেট করুন )। ACK-এ প্রতীক তালিকা এবং ABI উপস্থাপনা আপডেট করার উদাহরণের জন্য, aosp/1367601 পড়ুন।
কার্নেল 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 সামঞ্জস্য না ভাঙতে, এই পদক্ষেপগুলি অনুসরণ করুন:
প্যাচসেটের জন্য একটি কোড-রিভিউ +2 পাওয়ার জন্য অপেক্ষা করুন।
আপনার কোড পরিবর্তন এবং 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 অমিল সমাধান করতে নিম্নলিখিত পদক্ষেপগুলি ব্যবহার করুন:
নিম্নলিখিত কমান্ডে দেখানো হিসাবে
--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
পতাকা ইতিমধ্যেই স্পষ্টভাবে সেট করা আছে।নিম্নলিখিত কমান্ডটি ব্যবহার করে
.c
ফাইলটি সন্ধান করুন যেখানে CRC অমিল সহ চিহ্নটি রপ্তানি করা হয়েছে: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.symtypes
অ্যান্ড্রয়েড 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 bool
কোন
x#
উপসর্গ ছাড়া কী শুধুমাত্র প্রতীক নাম। যেমন:find_module s#module * find_module ( const char * )
দুটি ফাইল তুলনা করুন এবং সমস্ত পার্থক্য ঠিক করুন।
সমস্যাযুক্ত পরিবর্তনের ঠিক আগে এবং তারপর সমস্যাযুক্ত পরিবর্তনের সময় একটি বিল্ড দিয়ে symtypes
তৈরি করা ভাল। সমস্ত ফাইল সংরক্ষণ করা মানে তারা বাল্ক তুলনা করা যেতে পারে.
যেমন,
for f in $(find good bad -name '*.symtypes' | sed -r 's;^(good|bad)/;;' | LANG=C sort -u); do
diff -N -U0 --label good/"$f" --label bad/"$f" <(LANG=C sort good/"$f") <(LANG=C sort bad/"$f")
done
অন্যথায়, শুধুমাত্র আগ্রহের নির্দিষ্ট ফাইল তুলনা করুন.
কেস 1: ডেটা টাইপ দৃশ্যমানতার কারণে পার্থক্য
একটি নতুন #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 কার্নেলের সম্পূর্ণ টাইপ সংজ্ঞা থাকে, কিন্তু আপনার কার্নেলে এটি অনুপস্থিত থাকে (খুবই অসম্ভাব্য), তাহলে আপনার কার্নেলে সর্বশেষ অ্যান্ড্রয়েড কমন কার্নেলটি মার্জ করুন যাতে আপনি সর্বশেষ 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
ম্যাক্রো ইনভোকেশনের বিভিন্ন সেট বিতরণ করতে হতে পারে যা পরোক্ষভাবে অতিরিক্ত টাইপ সংজ্ঞাগুলিকে টানতে পারে কারণ তাদের মধ্যে কিছু টাইপ সংজ্ঞা ইতিমধ্যেই থাকতে পারে।
পঠনযোগ্যতার জন্য, সোর্স ফাইলের শুরুতে এই ধরনের ম্যাক্রো আহ্বান রাখুন।
অ্যান্ড্রয়েড 15 এবং তার নিচের জন্য রেজোলিউশন
প্রায়শই, ফিক্সটি শুধুমাত্র নতুন #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
ফাইলটিতে একটি 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 কার্নেলে অনুপস্থিত।
কেস 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 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-এর কিছু কাঠামো বিদ্যমান বিক্রেতা মডিউলগুলিকে না ভেঙে তাদের এক্সটেনশনের অনুমতি দেওয়ার জন্য প্যাড করা হয়েছে। যদি একটি আপস্ট্রিম কমিট (উদাহরণস্বরূপ) এই জাতীয় কাঠামোতে একজন সদস্যকে যুক্ত করে, তবে পরিবর্তে কিছু প্যাডিং ব্যবহার করার জন্য এটি পরিবর্তন করা সম্ভব হতে পারে। এই পরিবর্তনটি তখন সিআরসি গণনা থেকে লুকানো হয়।
মানসম্মত, স্ব-নথিভুক্ত ম্যাক্রো 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
দ্বারা ব্যবহৃত জিনিসগুলি রয়েছে।
struct data {
u64 handle;
ANDROID_KABI_USE(1, void *sekret);
ANDROID_KABI_RESERVE(2);
};
Android 16 এবং উচ্চতর জন্য রেজোলিউশন
CRCs গণনা করা হয় gendwarfksyms
দ্বারা যা 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 প্রতিনিধিত্ব বা উভয়কেই প্রভাবিত করতে পারে।
এটি সিআরসি গণনা থেকে এটি আড়াল করবে:
void *data;
bool urgent;
+ ANDROID_KABI_IGNORE(1, bool retry);
void *scratch_space;
সদস্য retry
উপলব্ধ হয় যেন এটি সরাসরি ঘোষণা করা হয়েছে, কিন্তু ম্যাক্রো প্রকৃতপক্ষে একটি বেনামী ইউনিয়ন সদস্যের সাথে সম্প্রসারিত হয় যাতে retry
পাশাপাশি symtype স্থিতিশীলতা বজায় রাখতে gendwarfksyms
দ্বারা ব্যবহৃত জিনিসগুলি রয়েছে।
নতুন সদস্যদের সাথে একটি কাঠামোর সম্প্রসারণ
সদস্যদের মাঝে মাঝে একটি কাঠামোর শেষে যোগ করা হয়। এটি বিদ্যমান সদস্যদের অফসেটকে প্রভাবিত করে না বা কাঠামোর বিদ্যমান ব্যবহারকারীদের প্রভাবিত করে না যারা শুধুমাত্র পয়েন্টার দ্বারা এটি অ্যাক্সেস করে। কাঠামোর আকার এটির 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");
পঠনযোগ্যতার জন্য, টাইপ বা প্রতীক সংজ্ঞার ঠিক পরে এটি রাখুন।
অ্যান্ড্রয়েড 15 এবং তার নিচের জন্য রেজোলিউশন
টাইপ এবং সিম্বল টাইপ পরিবর্তন genksyms
থেকে লুকানো প্রয়োজন। এটি __GENKSYMS__
দিয়ে প্রিপ্রসেসিং নিয়ন্ত্রণ করে করা যেতে পারে।
নির্বিচারে কোড রূপান্তর এইভাবে প্রকাশ করা যেতে পারে।
উদাহরণস্বরূপ, বিদ্যমান কাঠামোর একটি গর্ত দখলকারী একটি নতুন সদস্যকে আড়াল করতে:
struct parcel {
void *data;
bool urgent;
#ifndef __GENKSYMS__
bool retry;
#endif
void *scratch_space;
};