Anda dapat menggunakan alat Pemantauan Antarmuka Biner (ABI) aplikasi, tersedia di Android 11 dan lebih tinggi, untuk menstabilkan ABI dalam kernel dari kernel Android. Alat ini mengumpulkan dan membandingkan representasi ABI dari binari kernel yang ada ( vmlinux
+ modul). Representasi ABI ini adalah file .xml
dan daftar simbol. Antarmuka di mana representasi memberikan tampilan disebut Antarmuka Modul Kernel (KMI). Anda dapat menggunakan alat ini untuk melacak dan mengurangi perubahan pada KMI.
Alat pemantauan ABI dikembangkan di AOSP dan menggunakan libabigail
untuk menghasilkan dan membandingkan representasi.
Halaman ini menjelaskan perkakas, proses pengumpulan dan analisis representasi ABI, dan penggunaan representasi tersebut untuk memberikan stabilitas pada ABI dalam kernel. Halaman ini juga menyediakan informasi untuk memberikan kontribusi perubahan pada kernel Android.
Direktori ini berisi alat khusus untuk analisis ABI. Gunakan dengan skrip build yang disediakan oleh build_abi.sh
.)
Proses
Menganalisis ABI kernel membutuhkan beberapa langkah, yang sebagian besar dapat dilakukan secara otomatis:
- Dapatkan rantai alat, skrip build, dan sumber kernel melalui
repo
. - Berikan prasyarat apa pun (seperti perpustakaan
libabigail
dan koleksi alat). - Bangun kernel dan representasi ABI-nya .
- Analisis perbedaan ABI antara build dan referensi .
- Perbarui representasi ABI (jika diperlukan) .
- Bekerja dengan daftar simbol .
Instruksi berikut berfungsi untuk kernel apa pun yang dapat Anda buat menggunakan rantai alat yang didukung (seperti rantai alat Clang bawaan). repo manifests
tersedia untuk semua cabang kernel umum Android dan untuk beberapa kernel khusus perangkat, manifes tersebut memastikan bahwa rantai alat yang benar digunakan saat Anda membangun distribusi kernel untuk analisis.
Gunakan alat Pemantauan ABI
1. Dapatkan rantai alat, skrip build, dan sumber kernel melalui repo
Anda dapat memperoleh rantai alat, membuat skrip (skrip ini), dan sumber kernel dengan repo
. Untuk dokumentasi mendetail, lihat informasi terkait untuk membuat kernel Android .
Untuk mengilustrasikan prosesnya, langkah-langkah berikut menggunakan common-android12-5.10
, cabang kernel Android, yang merupakan kernel GKI terbaru yang dirilis pada saat penulisan ini. Untuk mendapatkan cabang ini melalui repo
, jalankan yang berikut:
repo init -u https://android.googlesource.com/kernel/manifest -b common-android12-5.10
repo sync
2. Berikan prasyarat
Alat ABI menggunakan libabigail
, perpustakaan dan kumpulan alat, untuk menganalisis binari. Satu set binari prebuilt yang sesuai dilengkapi dengan kernel-build-tools dan secara otomatis digunakan dengan build_abi.sh
.
Untuk memanfaatkan perkakas tingkat rendah (seperti dump_abi
), tambahkan alat kernel-build- ke PATH
.
3. Bangun kernel dan representasi ABI-nya
Pada titik ini Anda siap membangun kernel dengan rantai alat yang benar dan mengekstrak representasi ABI dari binernya ( vmlinux
+ modules).
Mirip dengan proses pembuatan kernel Android biasa (menggunakan build.sh
), langkah ini membutuhkan menjalankan build_abi.sh
.
BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh
Itu membangun kernel dan mengekstrak representasi ABI ke dalam subdirektori out_abi
. Dalam hal ini out/android12-5.10/dist/abi.xml
adalah tautan simbolis ke out_abi/android12-5.10/dist/abi-<id>.xml
. < id>
dihitung dengan mengeksekusi git describe
terhadap pohon sumber kernel.
4. Analisis perbedaan ABI antara build dan representasi referensi
build_abi.sh
menganalisis dan melaporkan setiap perbedaan ABI ketika referensi diberikan melalui variabel lingkungan ABI_DEFINITION
. ABI_DEFINITION
harus menunjuk ke file referensi relatif terhadap pohon sumber kernel, dan dapat ditentukan pada baris perintah atau, lebih umum, sebagai nilai dalam build.config . Berikut ini memberikan contoh:
BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh
Pada perintah di atas, build.config.gki.aarch64
mendefinisikan file referensi (sebagai ABI_DEFINITION=android/abi_gki_aarch64.xml
), dan diff_abi
memanggil abidiff
untuk membandingkan representasi ABI yang baru dibuat dengan file referensi. build_abi.sh
mencetak lokasi laporan dan mengeluarkan laporan singkat untuk setiap kerusakan ABI. Jika kerusakan terdeteksi, build_abi.sh
berhenti dan mengembalikan kode keluar yang bukan nol.
5. Perbarui representasi ABI (jika diperlukan)
Untuk memperbarui representasi ABI, aktifkan build_abi.sh
dengan flag --update
. Ini memperbarui file abi.xml
yang sesuai yang ditentukan oleh build.config
. Untuk mencetak perbedaan ABI karena pembaruan, aktifkan skrip dengan --print-report
. Pastikan untuk menyertakan laporan dalam pesan komit saat memperbarui file abi.xml
.
6. Bekerja dengan daftar simbol
Parameterisasi build_abi.sh
dengan daftar simbol KMI untuk memfilter simbol selama ekstraksi ABI. Ini adalah file teks biasa yang mencantumkan simbol kernel ABI yang relevan. Misalnya, file daftar simbol dengan konten berikut membatasi analisis ABI ke simbol ELF dengan nama symbol1
dan symbol2
:
[abi_symbol_list]
symbol1
symbol2
Perubahan pada simbol ELF lainnya tidak dipertimbangkan. File daftar simbol dapat ditentukan dalam file konfigurasi build.config yang sesuai dengan build.config
KMI_SYMBOL_LIST=
sebagai file yang relatif terhadap direktori sumber kernel ( $KERNEL_DIR
). Untuk memberikan tingkat organisasi, Anda dapat menentukan file daftar simbol tambahan dengan menggunakan ADDITIONAL_KMI_SYMBOL_LISTS=
dalam file build.config
. Ini menentukan file daftar simbol lebih lanjut, relatif terhadap $KERNEL_DIR
; pisahkan beberapa nama file dengan spasi.
Untuk membuat daftar simbol awal atau memperbarui yang sudah ada , Anda harus menggunakan skrip build_abi.sh
dengan parameter --update-symbol-list
.
Ketika skrip dijalankan dengan konfigurasi yang sesuai, skrip akan membangun kernel dan mengekstrak simbol yang diekspor dari modul vmlinux
dan GKI dan yang diperlukan oleh modul lain di pohon.
Pertimbangkan vmlinux
mengekspor simbol berikut (biasanya dilakukan melalui makro EXPORT_SYMBOL*
):
func1
func2
func3
Juga, bayangkan ada dua modul vendor, modA.ko
dan modB.ko
, yang memerlukan simbol berikut (dengan kata lain, mereka mencantumkan entri simbol yang undefined
dalam tabel simbol mereka):
modA.ko: func1 func2
modB.ko: func2
Dari sudut pandang stabilitas ABI, func1
dan func2
harus tetap stabil, karena digunakan oleh modul eksternal. Sebaliknya, ketika func3
diekspor, func3 tidak digunakan secara aktif (dengan kata lain, tidak diperlukan) oleh modul apa pun. Jadi, daftar simbol hanya berisi func1
dan func2
.
Untuk membuat atau memperbarui daftar simbol yang ada, build_abi.sh
harus dijalankan sebagai berikut:
BUILD_CONFIG=path/to/build.config.device build/build_abi.sh --update-symbol-list
Dalam contoh ini, build.config.device
harus menyertakan beberapa opsi konfigurasi:
-
vmlinux
harus ada dalam daftarFILES
. -
KMI_SYMBOL_LIST
harus disetel dan diarahkan ke daftar simbol KMI untuk diperbarui. -
GKI_MODULES_LIST
harus disetel dan diarahkan ke daftar modul GKI. Jalur ini biasanyaandroid/gki_aarch64_modules
.
Bekerja dengan alat ABI tingkat lebih rendah
Sebagian besar pengguna hanya perlu menggunakan build_abi.sh
. Dalam beberapa kasus, bekerja secara langsung dengan perangkat ABI tingkat lebih rendah mungkin diperlukan. Dua perintah yang digunakan oleh build_abi.sh
, dump_abi
dan diff_abi
, tersedia untuk mengekstrak dan membandingkan file ABI. Lihat bagian berikut untuk penggunaannya.
Buat representasi ABI dari pohon kernel
Disediakan pohon kernel linux dengan vmlinux
dan modul kernel yang dibangun, alat dump_abi
membuat representasi ABI menggunakan alat ABI yang dipilih. Contoh permintaan terlihat seperti ini:
dump_abi --linux-tree path/to/out --out-file /path/to/abi.xml
File abi.xml
berisi representasi ABI tekstual dari gabungan, ABI yang dapat diamati dari vmlinux
dan modul kernel di direktori yang diberikan. File ini dapat digunakan untuk inspeksi manual, analisis lebih lanjut, atau sebagai file referensi untuk menegakkan stabilitas ABI.
Bandingkan representasi ABI
Representasi ABI yang dibuat oleh dump_abi
dapat dibandingkan dengan diff_abi
. Gunakan alat-abi yang sama untuk dump_abi
dan diff_abi
. Contoh permintaan terlihat seperti ini:
diff_abi --baseline abi1.xml --new abi2.xml --report report.out
Daftar laporan yang dihasilkan mendeteksi perubahan ABI yang memengaruhi KMI. File yang ditentukan sebagai baseline
dan new
adalah representasi ABI yang dikumpulkan dengan dump_abi
. diff_abi
menyebarkan kode keluar dari alat yang mendasarinya dan oleh karena itu mengembalikan nilai bukan nol ketika ABI yang dibandingkan tidak kompatibel.
Filter representasi dan simbol KMI
Untuk memfilter representasi yang dibuat dengan dump_abi
atau untuk memfilter simbol yang dibandingkan dengan diff_abi
, gunakan parameter --kmi-symbol-list
, yang mengambil jalur ke file daftar simbol KMI:
dump_abi --linux-tree path/to/out --out-file /path/to/abi.xml --kmi-symbol-list /path/to/symbol_list_file
Bekerja dengan daftar simbol
KMI tidak menyertakan semua simbol di kernel atau bahkan semua dari 30.000+ simbol yang diekspor. Sebagai gantinya, simbol yang dapat digunakan oleh modul secara eksplisit terdaftar dalam satu set file daftar simbol yang dikelola secara publik di akar pohon kernel. Penyatuan semua simbol di semua file daftar simbol mendefinisikan kumpulan simbol KMI yang dipertahankan sebagai stabil. Contoh file daftar simbol adalah abi_gki_aarch64_db845c , yang menyatakan simbol yang diperlukan untuk DragonBoard 845c .
Hanya simbol yang tercantum dalam daftar simbol dan struktur serta definisi terkait yang dianggap sebagai bagian dari KMI. Anda dapat memposting perubahan ke daftar simbol Anda jika simbol yang Anda butuhkan tidak ada. Setelah antarmuka baru berada dalam daftar simbol, dan merupakan bagian dari deskripsi KMI, antarmuka tersebut dipertahankan sebagai stabil dan tidak boleh dihapus dari daftar simbol atau dimodifikasi setelah cabang dibekukan.
Setiap cabang kernel KMI Android Common Kernel (ACK) memiliki kumpulan daftar simbolnya sendiri. Tidak ada upaya yang dilakukan untuk memberikan stabilitas ABI antara cabang kernel KMI yang berbeda. Misalnya, KMI untuk android12-5.10
sepenuhnya independen dari KMI untuk android13-5.10
.
Alat ABI menggunakan daftar simbol KMI untuk membatasi antarmuka mana yang harus dipantau stabilitasnya. Daftar simbol utama berisi simbol-simbol yang diperlukan oleh modul kernel GKI. Vendor diharapkan mengirimkan dan memperbarui daftar simbol tambahan untuk memastikan bahwa antarmuka yang mereka andalkan menjaga kompatibilitas ABI. Misalnya, untuk melihat daftar daftar simbol untuk android13-5.15
, lihat https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android
Daftar simbol berisi simbol yang dilaporkan diperlukan untuk vendor atau perangkat tertentu. Daftar lengkap yang digunakan oleh alat ini adalah gabungan dari semua file daftar simbol KMI. Alat ABI menentukan detail setiap simbol, termasuk tanda tangan fungsi dan struktur data bersarang.
Saat KMI dibekukan, tidak ada perubahan yang diizinkan pada antarmuka KMI yang ada; mereka stabil. Namun, vendor bebas menambahkan simbol ke KMI kapan saja selama penambahan tersebut tidak mempengaruhi stabilitas ABI yang ada. Simbol yang baru ditambahkan dipertahankan stabil segera setelah dikutip oleh daftar simbol KMI. Simbol tidak boleh dihapus dari daftar kernel kecuali dapat dipastikan bahwa tidak ada perangkat yang pernah dikirimkan dengan ketergantungan pada simbol itu.
Anda dapat membuat daftar simbol KMI untuk perangkat menggunakan utilitas build/abi/extract_symbols
, yang mengekstrak dependensi simbol dari artefak build *.ko
. Utilitas ini menambahkan anotasi ke output dalam bentuk komentar, yang berguna dalam mengidentifikasi pengguna simbol. Saat mengirimkan daftar simbol ke ACK, menyimpan komentar ini sangat dianjurkan untuk memudahkan proses peninjauan. Untuk menghilangkan komentar, berikan --skip-module-grouping
saat menjalankan skrip extract_symbols
. Banyak mitra mengirimkan satu daftar simbol per ACK, tetapi ini bukan persyaratan yang sulit. Jika ini membantu pemeliharaan, Anda dapat mengirimkan beberapa daftar simbol.
Untuk bantuan dalam menyesuaikan daftar simbol dan menggunakan alat ABI tingkat tinggi dan rendah untuk debugging dan analisis mendetail, lihat Pemantauan ABI untuk Kernel Android .
Perpanjang KMI
Sementara simbol KMI dan struktur terkait dipertahankan sebagai stabil (berarti perubahan yang merusak antarmuka stabil dalam kernel dengan KMI beku tidak dapat diterima), kernel GKI tetap terbuka untuk ekstensi sehingga perangkat yang dikirim di akhir tahun tidak perlu tentukan semua dependensinya sebelum KMI dibekukan. Untuk memperluas KMI, Anda dapat menambahkan simbol baru ke KMI untuk fungsi kernel baru atau yang sudah ada, meskipun KMI dibekukan. Patch kernel baru juga diterima jika tidak merusak KMI.
Tentang kerusakan KMI
Kernel memiliki sumber dan biner dibangun berdasarkan sumber tersebut. Cabang kernel yang dipantau ABI termasuk abi.xml
yang merupakan representasi dari GKI ABI saat ini. Setelah biner dibangun (biner kernel, vmlinux
, Image
plus modul kernel), file abi.xml
dapat diekstraksi dari biner. Setiap perubahan yang dilakukan pada sumber kernel dapat mengubah biner dan mungkin juga mengubah abi.xml
yang diekstraksi (file yang diekstraksi setelah menerapkan perubahan dan membangun kernel). Penganalisis AbiAnalyzer
membandingkan dua file abi.xml
semantik dan menetapkan label Lint-1 pada perubahan jika menemukan masalah.
Menangani kerusakan ABI
Sebagai contoh, patch berikut memperkenalkan kerusakan ABI yang sangat jelas:
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 5ed8f6292a53..f2ecb34c7645 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -339,6 +339,7 @@ struct core_state {
struct kioctx_table;
struct mm_struct {
struct {
+ int dummy;
struct vm_area_struct *mmap; /* list of VMAs */
struct rb_root mm_rb;
u64 vmacache_seqnum; /* per-thread vmacache */
Saat Anda menjalankan build_abi.sh
lagi dengan tambalan ini diterapkan, perkakas keluar dengan kode kesalahan bukan nol dan melaporkan perbedaan ABI yang mirip dengan ini:
Leaf changes summary: 1 artifact changed
Changed leaf types summary: 1 leaf type changed
Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 0 Added function
Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable
'struct mm_struct at mm_types.h:372:1' changed:
type size changed from 6848 to 6912 (in bits)
there are data member changes:
[...]
Perbedaan ABI terdeteksi pada waktu pembuatan
Alasan paling umum untuk kesalahan adalah ketika driver menggunakan simbol baru dari kernel yang tidak ada dalam daftar simbol mana pun.
Jika simbol tidak disertakan dalam daftar simbol ( android/abi_gki_aarch64
), maka Anda harus terlebih dahulu memverifikasi bahwa itu diekspor dengan EXPORT_SYMBOL_GPL( symbol_name )
dan kemudian memperbarui representasi XML ABI dan daftar simbol. Misalnya, perubahan berikut menambahkan fitur FS Inkremental baru ke cabang android-12-5.10
, yang mencakup pembaruan daftar simbol dan representasi XML ABI.
- Contoh perubahan fitur ada di aosp/1345659 .
- Contoh daftar simbol ada di aosp/1346742 .
- Contoh perubahan XML ABI ada di aosp/1349377 .
Jika simbol diekspor (baik oleh Anda atau sebelumnya diekspor) tetapi tidak ada driver lain yang sedang menggunakannya, Anda mungkin mendapatkan kesalahan build yang mirip dengan berikut ini.
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
Untuk mengatasinya, perbarui daftar simbol KMI di kernel dan ACK Anda (lihat Memperbarui representasi ABI ). Untuk contoh memperbarui ABI XML dan daftar simbol di ACK, lihat aosp/1367601 .
Mengatasi kerusakan kernel ABI
Anda dapat menangani kerusakan ABI kernel dengan memfaktorkan ulang kode agar tidak mengubah ABI atau memperbarui representasi ABI . Gunakan bagan berikut untuk menentukan pendekatan terbaik untuk situasi Anda.
Gambar 1. Resolusi kerusakan ABI
Refactor kode untuk menghindari perubahan ABI
Lakukan segala upaya untuk menghindari modifikasi ABI yang ada. Dalam banyak kasus, Anda dapat memfaktorkan ulang kode Anda untuk menghapus perubahan yang memengaruhi ABI.
Memfaktorkan ulang perubahan bidang struct. Jika perubahan mengubah ABI untuk fitur debug, tambahkan
#ifdef
di sekitar bidang (di struct dan referensi sumber) dan pastikanCONFIG
yang digunakan untuk#ifdef
dinonaktifkan untuk defconfig produksi dangki_defconfig
. Untuk contoh bagaimana konfigurasi debug dapat ditambahkan ke struct tanpa merusak ABI, lihat patchset ini .Fitur refactoring untuk tidak mengubah kernel inti. Jika fitur baru perlu ditambahkan ke ACK untuk mendukung modul mitra, coba refactor bagian ABI dari perubahan untuk menghindari modifikasi kernel ABI. Untuk contoh penggunaan ABI kernel yang ada untuk menambahkan fungsionalitas tambahan tanpa mengubah ABI kernel, lihat aosp/1312213 .
Perbaiki ABI yang rusak di Android Gerrit
Jika Anda tidak dengan sengaja merusak kernel ABI, maka Anda perlu menyelidikinya, menggunakan panduan yang disediakan oleh alat pemantauan ABI. Penyebab paling umum kerusakan adalah fungsi yang ditambahkan atau dihapus, struktur data yang diubah, atau perubahan pada ABI yang disebabkan oleh penambahan opsi konfigurasi yang mengarah ke salah satu dari yang disebutkan di atas. Mulailah dengan mengatasi masalah yang ditemukan oleh alat.
Anda dapat mereproduksi pengujian ABI secara lokal dengan menjalankan perintah berikut dengan argumen yang sama yang akan Anda gunakan untuk menjalankan build/build.sh
:
Ini adalah contoh perintah untuk kernel GKI:
BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh
Tentang label Lint-1
Jika Anda mengunggah perubahan ke cabang yang berisi KMI yang dibekukan atau diselesaikan, perubahan tersebut harus melewati ABIAnalyzer
untuk memastikan perubahan tidak memengaruhi ABI stabil dengan cara yang tidak kompatibel. Selama proses ini, ABIAnalyzer
mencari laporan ABI yang dibuat selama build (build diperpanjang yang menjalankan build normal dan kemudian beberapa langkah ekstraksi dan perbandingan ABI. Jika ABIAnalyzer
menemukan laporan yang tidak kosong, ia menetapkan label Lint-1 dan perubahan diblokir dari pengiriman hingga diselesaikan; hingga patchset menerima label Lint+1.
Perbarui ABI Kernel
Jika Anda perlu memperbarui representasi ABI kernel, maka Anda harus memperbarui file abi.xml
yang sesuai di pohon sumber kernel. Cara paling mudah untuk melakukan ini adalah dengan menggunakan build/build_abi.sh
seperti:
build/build_abi.sh --update --print-report
Gunakan argumen yang sama dengan yang Anda gunakan untuk menjalankan build/build.sh
. Ini memperbarui abi.xml
yang benar di pohon sumber dan mencetak perbedaan yang terdeteksi. Sebagai praktik, sertakan laporan tercetak (pendek) dalam pesan komit (setidaknya sebagian).
Perbarui representasi ABI
Jika memodifikasi ABI tidak dapat dihindari, maka kode Anda berubah dan XML ABI serta daftar simbol perlu diterapkan ke ACK. Agar Lint menghapus -1 dan tidak merusak kompatibilitas GKI, lakukan langkah-langkah berikut:
Gabungkan perubahan kode Anda dan perubahan pembaruan ABI.
Unggah perubahan kode ABI ke ACK
Memperbarui ACK ABI tergantung pada jenis perubahan yang dilakukan.
Jika perubahan ABI terkait dengan fitur yang memengaruhi pengujian CTS atau VTS, perubahan tersebut biasanya dapat dipilih menjadi ACK apa adanya. Sebagai contoh:
- aosp/1289677 diperlukan agar audio berfungsi.
- aosp/1295945 diperlukan agar USB berfungsi.
Jika perubahan ABI adalah untuk fitur yang dapat dibagikan dengan ACK, perubahan itu dapat dipilih secara cermat menjadi ACK apa adanya. Misalnya, perubahan berikut tidak diperlukan untuk pengujian CTS atau VTS tetapi boleh dibagikan dengan ACK:
- aosp/1250412 adalah perubahan fitur termal.
- aosp/1288857 adalah perubahan
EXPORT_SYMBOL_GPL
.
Jika perubahan ABI memperkenalkan fitur baru yang tidak perlu disertakan dalam ACK, Anda dapat memperkenalkan simbol ke ACK menggunakan rintisan seperti yang dijelaskan di bagian berikut.
Gunakan rintisan untuk ACK
Rintisan harus diperlukan hanya untuk perubahan kernel inti yang tidak menguntungkan ACK, seperti perubahan kinerja dan daya. Daftar berikut ini merinci contoh stub dan sebagian cherry-picks di ACK untuk GKI.
Rintisan fitur isolasi inti ( aosp/1284493 ). Fungsionalitas di ACK tidak diperlukan, tetapi simbol harus ada di ACK agar modul Anda dapat menggunakan simbol ini.
Simbol placeholder untuk modul vendor ( aosp/1288860 ).
Fitur pelacakan peristiwa
mm
per proses khusus ABI ( aosp/1288454 ). Patch asli dipilih untuk ACK dan kemudian dipangkas untuk menyertakan hanya perubahan yang diperlukan untuk menyelesaikan perbedaan ABI untuktask_struct
danmm_event_count
. Tambalan ini juga memperbarui enummm_event_type
untuk memuat anggota terakhir.Pilihan ceri parsial dari perubahan ABI struct termal yang membutuhkan lebih dari sekadar menambahkan bidang ABI baru.
Patch aosp/1255544 menyelesaikan perbedaan ABI antara kernel mitra dan ACK.
Patch aosp/1291018 memperbaiki masalah fungsional yang ditemukan selama pengujian GKI dari tambalan sebelumnya. Perbaikannya termasuk menginisialisasi struct parameter sensor untuk mendaftarkan beberapa zona termal ke satu sensor.
CONFIG_NL80211_TESTMODE
Perubahan ABI ( aosp/1344321 ). Patch ini menambahkan perubahan struct yang diperlukan untuk ABI dan memastikan kolom tambahan tidak menyebabkan perbedaan fungsional, memungkinkan mitra untuk menyertakanCONFIG_NL80211_TESTMODE
dalam kernel produksi mereka dan tetap mempertahankan kepatuhan GKI.
Perbarui file ACK ABI
Untuk memperbarui file ACK ABI:
Unggah perubahan ABI dan tunggu untuk menerima Code-Review +2 untuk patchset.
Perbarui file ACK ABI.
cp partner kernel/android/abi_gki_aarch64_partner ACK kernel/abi_gki_aarch64_partner
BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh --update
Lakukan pembaruan ABI:
cd common
git add android/abi*
git commit -s -F $DIST_DIR/abi.report.short
<push to gerrit>
$DIST_DIR/abi.report.short
berisi laporan singkat tentang perubahan. Menggunakan flag-F
dengangit commit
secara otomatis menggunakan laporan untuk teks komit, yang kemudian dapat Anda edit untuk menambahkan baris subjek (atau potong jika pesannya terlalu panjang).
Cabang Kernel Android dengan ABI yang telah ditentukan sebelumnya
Beberapa cabang kernel hadir dengan representasi ABI yang telah ditentukan sebelumnya untuk Android sebagai bagian dari distribusi sumbernya. Representasi ABI ini dimaksudkan agar akurat, dan untuk mencerminkan hasil build_abi.sh
seolah-olah Anda akan menjalankannya sendiri. Karena ABI sangat dipengaruhi oleh berbagai opsi konfigurasi kernel, file .xml
ini biasanya termasuk dalam konfigurasi tertentu. Misalnya, cabang common-android12-5.10
berisi abi_gki_aarch64.xml
yang sesuai dengan hasil build saat menggunakan build.config.gki.aarch64
. Secara khusus, build.config.gki.aarch64
juga merujuk ke file ini melalui ABI_DEFINITION
.
Representasi ABI yang telah ditentukan sebelumnya digunakan sebagai definisi dasar saat membandingkan dengan diff_abi
. Misalnya, untuk memvalidasi patch kernel terkait perubahan apa pun pada ABI, buat representasi ABI dengan patch yang diterapkan dan gunakan diff_abi
untuk membandingkannya dengan ABI yang diharapkan untuk struktur atau konfigurasi sumber tertentu. Jika ABI_DEFINITION
disetel, menjalankan build_abi.sh
akan berhasil.
Terapkan KMI saat runtime
Kernel GKI menggunakan opsi TRIM_UNUSED_KSYMS=y
dan UNUSED_KSYMS_WHITELIST=<union of all symbol lists>
, yang membatasi simbol yang diekspor (seperti simbol yang diekspor menggunakan EXPORT_SYMBOL_GPL()
) ke yang terdaftar di daftar simbol. Semua simbol lain tidak diekspor, dan memuat modul yang membutuhkan simbol yang tidak diekspor ditolak. Pembatasan ini diberlakukan pada waktu pembuatan dan entri yang hilang ditandai.
Untuk tujuan pengembangan, Anda dapat menggunakan build kernel GKI yang tidak menyertakan pemangkasan simbol (artinya semua simbol yang biasanya diekspor dapat digunakan). Untuk menemukan build ini, cari build kernel_debug_aarch64
di ci.android.com .
Terapkan KMI menggunakan versi modul
Kernel Generic Kernel Image (GKI) menggunakan pembuatan versi modul ( CONFIG_MODVERSIONS
) sebagai tindakan tambahan untuk menerapkan kepatuhan KMI saat runtime. Pembuatan versi modul dapat menyebabkan kegagalan ketidakcocokan pemeriksaan redundansi siklik (CRC) pada waktu muat modul jika KMI modul yang diharapkan tidak cocok dengan KMI vmlinux
. Misalnya, berikut ini adalah kegagalan umum yang terjadi pada waktu muat modul karena ketidakcocokan CRC untuk simbol 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 ''
Penggunaan versi modul
Pembuatan versi modul berguna karena alasan berikut:
Pembuatan versi modul menangkap perubahan dalam visibilitas struktur data. Jika modul mengubah struktur data buram, yaitu struktur data yang bukan bagian dari KMI, modul tersebut akan rusak setelah perubahan struktur di masa mendatang.
Sebagai contoh, perhatikan bidang
fwnode
distruct device
. Bidang ini HARUS buram untuk modul sehingga mereka tidak dapat membuat perubahan pada bidangdevice->fw_node
atau membuat asumsi tentang ukurannya.Namun, jika sebuah modul menyertakan
<linux/fwnode.h>
(secara langsung atau tidak langsung), maka bidangfwnode
distruct device
tidak lagi buram. Modul kemudian dapat membuat perubahan padadevice->fwnode->dev
ataudevice->fwnode->ops
. Skenario ini bermasalah karena beberapa alasan, dinyatakan sebagai berikut:Itu dapat mematahkan asumsi yang dibuat oleh kode kernel inti tentang struktur data internalnya.
Jika pembaruan kernel di masa mendatang mengubah
struct fwnode_handle
(tipe datafwnode
), maka modul tidak lagi berfungsi dengan kernel baru. Selain itu,abidiff
tidak akan menunjukkan perbedaan apa pun karena modul memecah KMI dengan memanipulasi struktur data internal secara langsung dengan cara yang tidak dapat ditangkap hanya dengan memeriksa representasi biner.
Modul saat ini dianggap tidak kompatibel dengan KMI ketika dimuat di kemudian hari oleh kernel baru yang tidak kompatibel. Pembuatan versi modul menambahkan pemeriksaan waktu proses untuk menghindari secara tidak sengaja memuat modul yang tidak kompatibel dengan KMI dengan kernel. Pemeriksaan ini mencegah masalah runtime yang sulit di-debug dan crash kernel yang mungkin diakibatkan oleh ketidakcocokan yang tidak terdeteksi di KMI.
abidiff
memiliki keterbatasan dalam mengidentifikasi perbedaan ABI dalam kasus berbelit-belit tertentu yang dapat ditangkap olehCONFIG_MODVERSIONS
.
Mengaktifkan pembuatan versi modul mencegah semua masalah ini.
Periksa ketidakcocokan CRC tanpa mem-boot perangkat
abidiff
membandingkan dan melaporkan ketidakcocokan CRC antar kernel. Alat ini memungkinkan Anda untuk menangkap ketidakcocokan CRC pada saat yang sama dengan perbedaan ABI lainnya.
Selain itu, build kernel lengkap dengan CONFIG_MODVERSIONS
diaktifkan menghasilkan file Module.symvers
sebagai bagian dari proses build normal. File ini memiliki satu baris untuk setiap simbol yang diekspor oleh kernel ( vmlinux
) dan modul. Setiap baris terdiri dari nilai CRC, nama simbol, ruang nama simbol, vmlinux
atau nama modul yang mengekspor simbol, dan jenis ekspor (misalnya, EXPORT_SYMBOL
versus EXPORT_SYMBOL_GPL
).
Anda dapat membandingkan file Module.symvers
antara build GKI dan build Anda untuk memeriksa perbedaan CRC dalam simbol yang diekspor oleh vmlinux
. Jika ada perbedaan nilai CRC dalam simbol apa pun yang diekspor oleh vmlinux
dan simbol itu digunakan oleh salah satu modul yang Anda muat di perangkat Anda, modul tidak dimuat.
Jika Anda tidak memiliki semua artefak build, tetapi memiliki file vmlinux
dari kernel GKI dan kernel Anda, Anda dapat membandingkan nilai CRC untuk simbol tertentu dengan menjalankan perintah berikut pada kedua kernel dan membandingkan hasilnya:
nm <path to vmlinux>/vmlinux | grep __crc_<symbol name>
Misalnya, perintah berikut memeriksa nilai CRC untuk simbol module_layout
:
nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout
Selesaikan ketidakcocokan CRC
Gunakan langkah-langkah berikut untuk mengatasi ketidakcocokan CRC saat memuat modul:
Bangun kernel GKI dan kernel perangkat Anda dengan menambahkan
KBUILD_SYMTYPES=1
ke perintah yang Anda gunakan untuk membangun kernel, seperti yang ditunjukkan pada perintah berikut:KBUILD_SYMTYPES=1 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
Perintah ini menghasilkan file
.symtypes
untuk setiap file.o
. Saat menggunakanbuild_abi.sh,
KBUILD_SYMTYPES=1
sudah ditetapkan secara implisit.Temukan file
.c
yang mengekspor simbol dengan ketidakcocokan CRC, menggunakan perintah berikut:cd common && git grep EXPORT_SYMBOL.*module_layout kernel/module.c:EXPORT_SYMBOL(module_layout);
File
.c
memiliki file.symtypes
yang sesuai di GKI, dan artefak build kernel perangkat Anda. Temukan file.c
menggunakan perintah berikut:cd out/$BRANCH/common && ls -1 kernel/module.* kernel/module.o kernel/module.o.symversions kernel/module.symtypes
Berikut ini adalah ciri-ciri file
.c
:Format file
.c
adalah satu (berpotensi sangat panjang) baris per simbol.[s|u|e|etc]#
di awal baris berarti simbol bertipe data[struct|union|enum|etc]
. Sebagai contoh:t#bool typedef _Bool bool
Awalan
#
yang hilang di awal baris menunjukkan bahwa simbol adalah fungsi. Sebagai contoh:find_module s#module * find_module ( const char * )
Bandingkan kedua file dan perbaiki semua perbedaannya.
Kasus 1: Perbedaan karena visibilitas tipe data
Jika satu kernel menyimpan simbol atau tipe data buram ke modul dan kernel lainnya tidak, perbedaan itu muncul di antara file .symtypes
dari dua kernel. File .symtypes
dari salah satu kernel memiliki UNKNOWN
untuk simbol dan file .symtypes
dari kernel lain memiliki tampilan simbol atau tipe data yang diperluas.
Misalnya, menambahkan baris berikut ke file include/linux/device.h
di kernel Anda menyebabkan ketidakcocokan CRC, salah satunya adalah untuk module_layout()
:
#include <linux/fwnode.h>
Membandingkan module.symtypes
untuk simbol itu, memperlihatkan perbedaan berikut:
$ 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 ] ; }
...
Jika kernel Anda memiliki nilai UNKNOWN
dan kernel GKI memiliki tampilan simbol yang diperluas (sangat tidak mungkin), maka gabungkan Kernel Umum Android terbaru ke dalam kernel Anda sehingga Anda menggunakan basis kernel GKI terbaru.
Dalam kebanyakan kasus, kernel GKI memiliki nilai UNKNOWN
, tetapi kernel Anda memiliki detail simbol internal karena perubahan yang dilakukan pada kernel Anda. Ini karena salah satu file di kernel Anda menambahkan #include
yang tidak ada di kernel GKI.
Untuk mengidentifikasi #include
yang menyebabkan perbedaan, ikuti langkah-langkah berikut:
Buka file header yang mendefinisikan simbol atau tipe data yang memiliki perbedaan ini. Misalnya, edit
include/linux/fwnode.h
untukstruct fwnode_handle
.Tambahkan kode berikut di bagian atas file header:
#ifdef CRC_CATCH #error "Included from here" #endif
Dalam file
.c
modul yang memiliki ketidakcocokan CRC, tambahkan baris berikut sebagai baris pertama sebelum salah satu dari baris#include
.#define CRC_CATCH 1
Kompilasi modul Anda. Kesalahan waktu pembuatan yang dihasilkan menunjukkan rantai file header
#include
yang menyebabkan ketidakcocokan CRC ini. Sebagai contoh: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"
Salah satu tautan dalam rantai
#include
ini disebabkan oleh perubahan yang dibuat di kernel Anda, yang tidak ada di kernel GKI.Identifikasi perubahannya, kembalikan ke kernel Anda atau unggah ke ACK dan gabungkan .
Kasus 2: Perbedaan karena perubahan tipe data
Jika ketidakcocokan CRC untuk simbol atau tipe data bukan karena perbedaan visibilitas, itu karena perubahan aktual (penambahan, penghapusan, atau perubahan) pada tipe data itu sendiri. Biasanya, abidiff
menangkap ini, tetapi jika salah karena celah deteksi yang diketahui, mekanisme MODVERSIONS
dapat menangkapnya.
Misalnya, membuat perubahan berikut di kernel Anda menyebabkan beberapa ketidakcocokan CRC karena banyak simbol yang terpengaruh secara tidak langsung oleh jenis perubahan ini:
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);
Satu ketidakcocokan CRC adalah untuk devm_of_platform_populate()
.
Jika Anda membandingkan file .symtypes
untuk simbol itu, mungkin terlihat seperti ini:
$ 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 * ) ; ...
Untuk mengidentifikasi jenis yang diubah, ikuti langkah-langkah berikut:
Temukan definisi simbol dalam kode sumber (biasanya dalam file
.h
).- Untuk perbedaan simbol sederhana antara kernel Anda dan kernel GKI, temukan komit dengan menjalankan perintah berikut:
git blame
- Untuk simbol yang dihapus (di mana simbol dihapus di pohon dan Anda juga ingin menghapusnya di pohon lain), Anda perlu menemukan perubahan yang menghapus baris. Gunakan perintah berikut di pohon tempat baris dihapus:
git log -S "copy paste of deleted line/word" -- <file where it was deleted>
Tinjau daftar komit yang dikembalikan untuk menemukan perubahan atau penghapusan. Komit pertama mungkin yang Anda cari. Jika tidak, buka daftar sampai Anda menemukan komit.
Setelah Anda mengidentifikasi perubahan, kembalikan ke kernel Anda atau unggah ke ACK dan gabungkan .