אפשר להשתמש בכלי למעקב אחרי ממשק בינארי של אפליקציה (ABI), שזמינים ב-
Android מגרסה 11 ואילך, כדי לייצב את הליבה (kernel)
ממשק ABI של הליבה של Android. הכלי אוסף ייצוגי ABI ומשווה ביניהם
מקובצי ליבה בינאריים קיימים (vmlinux
+ מודולים של GKI). ה-ABI הזה
הם הקבצים .stg
ורשימות הסמלים. הממשק ב-
שהייצוג מעניק לתצוגה נקרא ממשק מודול ליבה (Kernel)
(KMI). בעזרת הכלים האלה תוכלו לעקוב אחרי שינויים ב-KMI ולצמצם אותם.
הכלים למעקב ABI
מפתח ב-AOSP
ומשתמשת
STG (או
libabigail
ב-
Android מגרסה 13 ומטה) כדי ליצור ולהשוות.
של משפטים יחידים,
בדף הזה נתאר את הכלים, תהליך האיסוף והניתוח של ממשק ABI ושימוש בייצוגים כאלה כדי לספק יציבות של ה-ABI המובנה. הדף הזה כולל גם מידע לגבי השינויים לליבות (kernel) של Android.
תהליך
ניתוח ה-ABI של הליבה כולל מספר שלבים, שרובם יכולים להיות אוטומטיים:
- פיתוח הליבה וייצוג ה-ABI שלה
- ניתוח ההבדלים ב-ABI בין ה-build לבין קובץ עזר.
- מעדכנים את ייצוג ה-ABI (אם נדרש).
- עבודה עם רשימות סמלים.
ההוראות הבאות מיועדות לכל
הליבה (kernel) שאפשר ליצור באמצעות
(למשל, ה-toolchain מובנה מראש). repo manifests
זמינים לכל הסתעפויות הליבה (kernel) הנפוצות של Android,
בליבות ספציפיות למכשיר, הן מבטיחות שנעשה שימוש בצרור הכלים הנכון
לפתח התפלגות ליבה (kernel) לניתוח.
רשימות סמלים
ה-KMI לא כולל את כל הסמלים בליבה (kernel) או אפילו לא את כל סמלים שיוצאו. במקום זאת, הסמלים שבהם אפשר להשתמש במודולים של ספקים רשום במפורש בקבוצה של קובצי רשימת סמלים שמנוהלים באופן ציבורי ברמה הבסיסית (root) של עץ הליבה. איחוד של כל הסמלים בכל הקבצים של רשימת הסמלים מגדיר את קבוצת סמלי ה-KMI שנשמרת כיציבה. קובץ לדוגמה של רשימת סמלים תואם לערך abi_gki_aarch64_db845c, שמצהיר על הסמלים הנדרשים DragonBoard 845c.
רק הסמלים המפורטים ברשימת סמלים והמבנים הקשורים אליהם ההגדרות נחשבות לחלק מה-KMI. אפשר לפרסם שינויים ב אם הסמלים הדרושים לך לא נמצאים. אחרי השימוש בממשקים חדשים רשימת סמלים, והם חלק מתיאור ה-KMI, נשארות יציבות ואין להסיר אותו מרשימת הסמלים או לשנות אותו לאחר שההסתעפות קפוא.
לכל הסתעפות ליבה (KMI) של Android Common KMI יש קבוצת סמלים משלה.
רשימות. לא נעשה ניסיון לספק יציבות ABI בין ליבה (kernel) שונה של KMI
ענפים. לדוגמה, ה-KMI של android12-5.10
לא תלוי בכלל
את ה-KMI של android13-5.10
.
כלי ABI משתמשים ברשימות סמלים של KMI כדי להגביל את הממשקים שצריך לעקוב אחריהם
יציבות.
רשימת הסמלים הראשית
מכיל את הסמלים שנדרשים למודולים של הליבה של GKI. הספקים הם
לשלוח ולעדכן רשימות נוספות של סמלים, כדי להבטיח
והממשקים שעליהם הם מסתמכים כדי לשמור על תאימות ABI. לדוגמה, כדי לראות רשימה
ברשימות של סמלים עבור android13-5.15
,
https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android
רשימת סמלים מכילה את הסמלים שמדווחים כנחוצים עבור הישות הספציפית הספק או המכשיר שלך. הרשימה המלאה שמשמשת את הכלים היא איחוד של כל קובצי רשימת סמלים של KMI. כלי ABI קובעים את הפרטים של כל סמל, כולל ומבני נתונים מוטמעים.
בהקפאת ה-KMI, לא ניתן לבצע שינויים בממשקי ה-KMI הקיימים. שהם יציבים. עם זאת, הספקים רשאים להוסיף סמלים ל-KMI בכל שלב. כל עוד התוספות לא משפיעות על היציבות של ה-ABI הקיים. נוספו לאחרונה נשמרים ביציבות ברגע שמצוטטים ברשימה של סמלי KMI. אין להסיר סמלים מרשימה של ליבה (kernel) אלא אם ניתן לאמת אותם שאף מכשיר לא שלח אף מכשיר שתלוי בסמל הזה.
אפשר ליצור רשימת סמלי KMI עבור מכשיר מסוים בעזרת ההוראות הבאות: איך לעבוד עם רשימות סמלים שותפים רבים שולחים רשימת סמלים אחת לכל ACK, אבל זו לא דרישה קשה. אם הדבר עוזר בתחזוקה, אפשר לשלוח כמה רשימות של סמלים.
הרחבת KMI
למרות שסמלי KMI ומבנים קשורים נשמרים כיציבים (כלומר אי אפשר לגרום לשינויים של ממשקים יציבים בליבה (kernel) עם KMI קפוא הליבה של GKI תישאר פתוחה לתוספים, כדי שמשלוח המכשירים בהמשך השנה לא צריכים להגדיר את כל יחסי התלות לפני שה-KMI קפוא. כדי להרחיב את KMI אפשר להוסיף ל-KMI סמלים חדשים עבור פונקציות ליבה (kernel) קיימות שיוצאו, גם אם ה-KMI קפוא. ליבה חדשה ייתכן שיתקבלו גם תיקונים אם הם לא ישברו את ה-KMI.
מידע על תקלות ב-KMI
לליבה יש מקורות וקבצים בינאריים נוצרים מהמקורות האלה.
הסתעפויות ליבה (kernel) עם מעקב ABI כוללות ייצוג ABI של ה-GKI הנוכחי
ABI (בקובץ .stg
). אחרי הקבצים הבינאריים (vmlinux
, Image
וגם
מודולים של GKI), ניתן לחלץ ייצוג ABI
בינאריים. כל שינוי שמתבצע בקובץ מקור ליבה יכול להשפיע על הקבצים הבינאריים
הפנייה תשפיע גם על .stg
שחולץ. המנתח של AbiAnalyzer
משווה את
את קובץ .stg
שהוקצה באמצעות הקובץ שנשלף מפריטי ה-build ומגדיר
תווית איתור שגיאות בקוד (lint-1) בשינוי ב-Gerrit אם היא מזהה הבדל סמנטי.
טיפול בתקלות בממשק ה-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.
כשמריצים build 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 שזוהו בזמן ה-build
הסיבה השכיחה ביותר לשגיאות היא כשנהג משתמש בסמל חדש ליבה (kernel) שלא מופיעה באף אחת מרשימות הסמלים.
אם הסמל לא כלול ברשימת הסמלים (android/abi_gki_aarch64
),
אז צריך קודם לוודא שהייצוא מיוצא עם
EXPORT_SYMBOL_GPL(symbol_name)
ולאחר מכן מעדכנים את
ייצוג XML של ABI ורשימת סמלים. לדוגמה, השינויים הבאים מוסיפים
את התכונה החדשה של המרות מצטברות להסתעפות android-12-5.10
,
כולל עדכון של רשימת הסימנים וייצוג XML של ABI.
- דוגמה לשינוי תכונה נמצאת aosp/1345659.
- הדוגמה לרשימת הסמלים נמצאת aosp/1346742.
- דוגמה לשינוי XML ב-ABI aosp/1349377.
אם הסמל מיוצא (אתם או שהוא ייצא בעבר), אבל לא נהג אחר משתמש בו, יכול להיות שתתקבל שגיאת build שדומה לזו.
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
כדי לפתור את הבעיה, מעדכנים את רשימת סמלי ה-KMI גם בליבה (kernel) וגם ב-ACK (מידע נוסף זמין בקטע לעדכן את ייצוג ה-ABI). לדוגמה לעדכון ה-ABI XML ורשימת הסמלים ב-ACK, aosp/1367601.
פתרון תקלות ABI בליבה (kernel)
אפשר להתמודד עם תקלות ABI בליבה (kernel) על ידי ארגון מחדש של הקוד כך שלא ישנה את ממשק ABI או עדכון של ייצוג ABI. צריך להשתמש בהגדרות הבאות כדי לקבוע את הגישה המתאימה ביותר למצב שלכם.
איור 1. רזולוציה של שבירת ABI
ארגון קוד מחדש כדי למנוע שינויים ב-ABI
עושים כל מאמץ כדי לא לשנות את ה-ABI הקיים. במקרים רבים, אפשר לארגן מחדש את הקוד כדי להסיר שינויים שמשפיעים על ה-ABI.
ארגון מחדש של שינויים בשדה struct. אם שינוי משנה את ה-ABI לניפוי באגים צריך להוסיף
#ifdef
מסביב לשדות (במבנים ובמקור הפניות) ולוודא שהשדהCONFIG
שמשמש את#ifdef
מושבת עבור הגדרת הייצור ו-gki_defconfig
. דוגמה לאופן שבו ניפוי באגים אפשר להוסיף config ל-build בלי לשבור את ה-ABI, כאן מוסבר איך עושים את זה. patchset.ארגון מחדש של התכונות כך שלא ישנו את הליבה (kernel) של הליבה. אם יש צורך בתכונות חדשות יתווסף ל-ACK כדי לתמוך במודולים של שותפים, נסו לשנות את ארגון ה-ABI חלק מהשינוי כדי להימנע משינוי ה-ABI של הליבה. לדוגמה לשימוש את ה-ABI הקיים של הליבה כדי להוסיף יכולות נוספות בלי לשנות את מתייחס ל-ABI של ליבה (kernel) aosp/1312213.
תיקון ממשק ABI לא תקין ב-Android Gerrit
אם לא שברתם באופן מכוון את ה-ABI של הליבה, תצטרכו לבדוק את הנושא בהתאם להנחיות של הכלים למעקב אחרי ממשק ABI. הבעיה הנפוצה ביותר הסיבות לשיבושים הם מבני נתונים משתנים והסמל המשויך ל-CRC או בגלל שינויים באפשרויות התצורה שמובילים לאחד מהערכים שצוינו למעלה. כדי להתחיל, צריך לטפל בבעיות שהכלי מצא.
אפשר לשחזר את ממצאי ה-ABI באופן מקומי, פיתוח הליבה וייצוג ה-ABI שלה
מידע על תוויות Linux-1
אם מעלים שינויים להסתעפות שמכילה KMI שהוקפא או סופי,
כדי לוודא שהשינויים לא ישפיעו על היציבות, השינויים חייבים לעבור את AbiAnalyzer
את ה-ABI בצורה לא תואמת. במהלך התהליך, AbiAnalyzer
מחפש את
דוח ABI שנוצר במהלך ה-build (build מורחב שמבצע את
build רגיל ואז כמה שלבי חילוץ ABI והשוואה.
אם השדה AbiAnalyzer
מוצא דוח שאינו ריק, מוגדרת התוויתlint-1 ופונקציית
ייחסם שליחה של שינוי עד שיטופל; עד שה-patchset מקבל
התווית Linux+1.
עדכון ה-ABI של הליבה
אם אי אפשר להימנע משינוי ה-ABI, צריך להחיל את השינויים בקוד את ייצוג ה-ABI, ואת רשימת הסמלים ל-ACK. כדי להגיע אל Linux להסיר את -1 ולא לשבור את התאימות של GKI, צריך לבצע את השלבים הבאים:
צריך להמתין לקבלת בדיקת קוד 2+ עבור ערכת התיקונים.
מיזוג השינויים בקוד והשינוי בעדכון ה-ABI.
העלאת שינויים בקוד ABI ל-ACK
העדכון של ה-ACK ABI תלוי בסוג השינוי שמבוצע.
אם שינוי ABI קשור לתכונה שמשפיעה על בדיקות CTS או VTS, בדרך כלל ניתן לבחור ב-ACK בדיוק כפי שהוא. מוצרים לדוגמה:
- aosp/1289677 נדרש כדי שהאודיו יפעל.
- aosp/1295945 נדרש כדי שה-USB יפעל.
אם שינוי ב-ABI מיועד לתכונה שאפשר לשתף עם ה-ACK, ניתן לבחור ב-ACK בדיוק כפי שהוא. לדוגמה, השינויים הבאים לא נחוצים לבדיקת CTS או VTS, אבל אפשר לשתף אותם עם ACK:
- aosp/1250412 הוא שינוי בתכונה תרמיים.
- aosp/1288857
הוא שינוי ב-
EXPORT_SYMBOL_GPL
.
אם בעקבות שינוי ב-ABI מופיעה תכונה חדשה שלא צריך לכלול את ACK, ניתן להציג את הסמלים של ACK באמצעות stub כפי שמתואר בסעיף הבא.
שימוש ב-stubs עבור ACK
ה-Stubs חייבים להיות נחוצים רק לביצוע שינויים בליבה (kernel) שלא משפרים את ACK, כמו שינויים בביצועים ובעוצמה. דוגמאות לפרטי הרשימה של stubs ובחירת זריזות חלקיות ב-ACK עבור GKI.
stub של פיצ'ר ליבה (aosp/1284493). היכולות ב-ACK לא נחוצות, אבל הסמלים צריכים להיות ב-ACK כדי שהמודולים ישתמשו בסמלים האלה.
סמל placeholder למודול ספק (aosp/1288860).
בחירת ממשק ABI בלבד: תכונת מעקב אחרי אירועים
mm
לפי תהליך (aosp/1288454). התיקון המקורי נבחר ב-ACK ואז נחתך כך שיכלול רק את השינויים הנדרשים כדי לפתור את הבדלי ה-ABI עבורtask_struct
mm_event_count
. בתיקון הזה גם מתבצע עדכון של ה-enummm_event_type
כך שיכלול חברי המועדון הסופיים.בדיקה חלקית של שינויים ב-ABI של מבנה תרמי, שדרשו יותר מאשר ולהוסיף את שדות ה-ABI החדשים.
מדבקה aosp/1255544 פתרנו הבדלים ב-ABI בין ליבה (kernel) של השותף לבין ACK.
מדבקה aosp/1291018 תוקנו הבעיות הפונקציונליות שנמצאו במהלך בדיקת ה-GKI של התיקון הקודם. התיקון כלל אתחול של מבנה הפרמטרים של החיישן כדי לרשום כמה אזורים תרמיים בחיישן אחד.
CONFIG_NL80211_TESTMODE
שינויים בממשק ABI (aosp/1344321). התיקון הזה הוסיף את שינויי ה-build הנדרשים ל-ABI ווידאת שהתיקון שדות נוספים לא גרמו להבדלים בפונקציונליות, ולכן השותפים אפשרו לכלול אתCONFIG_NL80211_TESTMODE
בליבות הייצור, ועדיין לשמור על תאימות ל-GKI.
אכיפת ה-KMI בזמן הריצה
הליבה של GKI משתמשת באפשרויות ההגדרה TRIM_UNUSED_KSYMS=y
ו-UNUSED_KSYMS_WHITELIST=<union
of all symbol lists>
, שמגבילות את הסמלים המיוצאים
(למשל סמלים שיוצאו באמצעות EXPORT_SYMBOL_GPL()
) לאלה שרשומים
של רשימת הסימנים. לא מתבצע ייצוא של כל שאר הסמלים, ומתבצעת טעינה של מודול שמחייב
הסמל שלא יוצא הייצוא נדחה. ההגבלה הזו נאכפת בזמן ה-build
רשומות חסרות מסומנות.
למטרות פיתוח, אפשר להשתמש ב-build של ליבה (kernel) של GKI שלא כולל
חיתוך סמלים (כלומר, ניתן להשתמש בכל הסמלים שמיוצאים בדרך כלל). כדי לאתר
את גרסאות ה-build האלה, צריך לחפש אתkernel_debug_aarch64
ci.android.com.
אכיפת ה-KMI באמצעות ניהול גרסאות של מודולים
הליבה הכללית של תמונת הליבה (GKI) משתמשת בניהול גרסאות של מודול
(CONFIG_MODVERSIONS
) כאמצעי נוסף לאכיפת התאימות של KMI
בסביבת זמן ריצה. ניהול גרסאות של מודולים עלול לגרום לחוסר התאמה בבדיקת יתירות מחזורית (CRC)
כשלים בזמן הטעינה של המודול אם ה-KMI הצפוי של מודול לא תואם
vmlinux
ק"מ. דוגמה לכשל אופייני שמתרחש
זמן הטעינה של המודול בגלל חוסר התאמה של CRC עבור הסמל 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, הן יפסיקו לפעול לאחר שינויים עתידיים במבנה.
לדוגמה, אפשר לראות את
fwnode
בשדהstruct device
. השדה הזה חייב להיות אטום למודולים כדי שהם לא יוכלו לבצע שינויים שלdevice->fw_node
או מניחים את הגודל שלו.עם זאת, אם המודול כולל את
<linux/fwnode.h>
(באופן ישיר או עקיף), אז השדהfwnode
ב-struct device
כבר לא אטום עבורו. המודול יוכל לבצע שינויים ב-device->fwnode->dev
אוdevice->fwnode->ops
. התרחיש הזה בעייתי מכמה סיבות: צוין כך:הוא יכול לשבור את ההנחות שקוד הליבה מרכזי עושה לגבי מבני נתונים.
אם עדכון ליבה עתידי ישנה את
struct fwnode_handle
(הנתונים מסוגfwnode
), המודול כבר לא עובד עם הליבה החדשה. בנוסף, הפונקציהstgdiff
לא תציג הבדלים כי המודול לא תקין של ה-KMI על ידי מניפולציה ישירה של מבני נתונים פנימיים בדרכים שלא על ידי בדיקה רק של הייצוג הבינארי.
מודול נוכחי לא תואם ל-KMI כשהוא נטען בתאריך מאוחר יותר על ידי ליבה חדשה שאינה תואמת. ניהול גרסאות של מודולים מוסיף בדיקת זמן ריצה ל- להימנע מטעינה בטעות של מודול שלא תואם ל-KMI עם הליבה. הבדיקה הזו מונעת בעיות בסביבת זמן ריצה קשה לניפוי באגים וקריסות ליבה שעשויות לגרום כתוצאה מחוסר תאימות לא מזוהה ב-KMI.
הפעלת ניהול הגרסאות של המודולים מונעת את כל הבעיות האלו.
בדיקת אי התאמות של CRC ללא אתחול המכשיר
stgdiff
משווה ומדווח על אי התאמות של CRC בין ליבות
הבדלים ב-ABI.
נוסף על כך, build של ליבה (kernel) מלאה שהופעל בו CONFIG_MODVERSIONS
יוצר
Module.symvers
כחלק מתהליך ה-build הרגיל. בקובץ הזה יש
לכל סמל שיוצאו על ידי הליבה (vmlinux
) והמודולים. כל אחד
השורה מורכבת מערך CRC, שם הסמל, מרחב השמות של הסמלים, vmlinux
או
שם המודול שמייצא את הסמל, ואת סוג הייצוא (לדוגמה,
EXPORT_SYMBOL
מול EXPORT_SYMBOL_GPL
).
אפשר להשוות בין קובצי Module.symvers
של גרסת ה-build של GKI לבין ה-build שלך
כדי לבדוק אם יש הבדלים ב-CRC לסמלים שיוצאו על ידי vmlinux
. אם יש
הוא הבדל בערך CRC בכל סמל שמיוצא על ידי vmlinux
וגם
משמש את אחד מהמודולים שטוענים במכשיר, המודול לא
טעינה.
אם אין לך את כל פריטי המידע שנוצרו בתהליך הפיתוח (Artifact) של ה-build, אבל יש לך את vmlinux
הקבצים של
את הליבה של GKI והליבה, תוכלו להשוות את ערכי ה-CRC
על ידי הרצת הפקודה הבאה על הליבה (kernel) והשוואת
פלט:
nm <path to vmlinux>/vmlinux | grep __crc_<symbol name>
לדוגמה, הפקודה הבאה בודקת את ערך ה-CRC של module_layout
סמל:
nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout
פתרון אי-התאמות של CRC
כדי לפתור אי התאמה של CRC כשטוענים מודול, אפשר לפעול לפי השלבים הבאים:
פיתוח ליבת GKI והליבה של המכשיר באמצעות
--kbuild_symtypes
כפי שמוצג בפקודה הבאה:tools/bazel run --kbuild_symtypes //common:kernel_aarch64_dist
הפקודה הזו יוצרת קובץ
.symtypes
לכל קובץ.o
. צפייהKBUILD_SYMTYPES
ב-Kleaf לקבלת פרטים.ל-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
מוגדר באופן מרומז כבר.מוצאים את הקובץ
.c
שבו מיוצא הסמל עם חוסר ההתאמה של CRC, באמצעות הפקודה הבאה:cd common && git grep EXPORT_SYMBOL.*module_layout kernel/module.c:EXPORT_SYMBOL(module_layout);
לקובץ
.c
יש קובץ.symtypes
תואם ב-GKI, ארטיפקטים של גרסת הליבה של המכשיר. מוצאים את הקובץ.c
באמצעות פקודות:cd out/$BRANCH/common && ls -1 kernel/module.* kernel/module.o kernel/module.o.symversions kernel/module.symtypes
אלה המאפיינים של הקובץ
.c
:הפורמט של הקובץ
.c
הוא שורה אחת (אולי ארוכה מאוד) לכל סמל.[s|u|e|etc]#
בתחילת השורה פירושו שהסמל הוא מסוג נתונים[struct|union|enum|etc]
. לדוגמה:t#bool typedef _Bool bool
אם חסרה קידומת
#
בתחילת השורה, סימן שהסמל הוא פונקציה. לדוגמה:find_module s#module * find_module ( const char * )
משווים בין שני הקבצים ומתקנים את כל ההבדלים.
מקרה 1: הבדלים בגלל הרשאות הגישה של סוגי הנתונים
אם ליבה אחת משאירה סמל או סוג נתונים אטומים למודולים והשני
אין ליבה (kernel), ההבדל הזה מופיע בין קובצי .symtypes
של שתי הליבות. בקובץ .symtypes
מאחת מהליבה יש UNKNOWN
עבור סמל, ולקובץ .symtypes
מהליבה השנייה יש תצוגה מורחבת
של הסמל או סוג הנתונים.
לדוגמה, הוספת השורה הבאה
הקובץ include/linux/device.h
בליבה (kernel) גורם לחוסר התאמה ב-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 ] ; }
...
אם ערך הליבה (kernel) שלך הוא UNKNOWN
וליבה של GKI יש תצוגה מורחבת
מהסמל (סביר מאוד שלא סביר), ואז למזג את הגרסה העדכנית ביותר של Android Common Kernel
את הליבה שלכם כדי להשתמש בבסיס הליבה העדכני של GKI.
ברוב המקרים, בליבה של GKI יש ערך של UNKNOWN
, אבל הליבה כוללת את
פרטים פנימיים של הסמל בגלל שינויים שבוצעו בליבה (kernel) שלך. הדבר
כי אחד מהקבצים בליבה (kernel) הוסיף #include
שלא נמצא ב-
הליבה של GKI.
לעיתים קרובות, התיקון רק מסתיר את #include
החדש מ-genksyms
.
#ifndef __GENKSYMS__
#include <linux/fwnode.h>
#endif
אחרת, כדי לזהות את ה#include
שגורם להבדל, פועלים לפי השלבים הבאים
שלבים:
פותחים את קובץ הכותרת שמגדיר את הסמל או את סוג הנתונים הבדל. לדוגמה, אפשר לערוך את
include/linux/fwnode.h
שלstruct fwnode_handle
.מוסיפים את הקוד הבא בחלק העליון של קובץ הכותרת:
#ifdef CRC_CATCH #error "Included from here" #endif
בקובץ
.c
של המודול שיש בו אי התאמה של CRC, מוסיפים את הקוד בתור השורה הראשונה לפני כל אחד משורות#include
.#define CRC_CATCH 1
עורכים את המודול. שגיאת זמן ה-build שמתקבלת מציגה את שרשרת קובץ הכותרת
#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
נובע משינוי שבוצע ב הליבה חסרה בליבה (kernel) של GKI.מזהים את השינוי, מבטלים אותו בליבה (kernel) או להעלות אותו אל ACK ולמזג אותו.
מקרה 2: הבדלים בגלל שינויים בסוג הנתונים
אם חוסר ההתאמה של ה-CRC בסמל או בסוג הנתונים לא נובע מהבדלים חשיפה, אז הדבר נובע משינויים שבוצעו בפועל (הוספות, הסרות או שינויים) סוג הנתונים עצמו.
לדוגמה, ביצוע השינוי הבא בליבה (kernel) גורם לכמה 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 * ) ; ...
כדי לזהות את הסוג שהשתנה, פועלים לפי השלבים הבאים:
אפשר למצוא את הגדרת הסמל בקוד המקור (בדרך כלל בקבצים מסוג
.h
).- להבדלים בסמלים בין הליבה שלכם לליבה של GKI, כדי למצוא את ההתחייבות, מריצים את הפקודה הבאה:
git blame
- לגבי סמלים שנמחקו (שבהם סמל נמחק בעץ וגם אם רוצים למחוק אותו בעץ האחר), צריך למצוא את השינוי מחק את השורה. משתמשים בפקודה הבאה בעץ שבו הקו נמחקה:
git log -S "copy paste of deleted line/word" -- <file where it was deleted>
בודקים את רשימת ההתחייבויות שהוחזרו כדי לאתר את השינוי או המחיקה. ההתחייבות הראשונה היא כנראה זו שאתם מחפשים. אם לא, לך תעברו על הרשימה עד שמוצאים את ההתחייבות.
אחרי זיהוי השינוי, מחזירים אותו למצב הליבה (kernel) או להעלות אותו ל-ACK ולקבל אותו ממוזג.