Pemantauan ABI kernel Android

Anda dapat menggunakan alat pemantauan antarmuka biner aplikasi (ABI), yang tersedia di Android 11 dan yang lebih tinggi, untuk menstabilkan kernel Android dalam kernel. Alat ini mengumpulkan dan membandingkan representasi ABI dari biner kernel yang ada (modul vmlinux+ GKI). Representasi ABI ini adalah file .stg dan daftar simbol. Antarmuka tempat representasi memberikan tampilan disebut Kernel Module Interface (KMI). Anda dapat menggunakan alat tersebut untuk melacak dan memitigasi perubahan pada KMI.

Alat pemantauan ABI dikembangkan di AOSP dan menggunakan STG (atau libabigail di Android 13 dan yang lebih lama) untuk membuat dan membandingkan representasi.

Halaman ini menjelaskan tentang alat, proses pengumpulan dan analisis representasi ABI, dan penggunaan representasi tersebut untuk memberikan stabilitas pada ABI dalam kernel. Halaman ini juga memberikan informasi untuk berkontribusi pada perubahan pada kernel Android.

Proses

Menganalisis ABI kernel memerlukan beberapa langkah, yang sebagian besar dapat diotomatiskan:

  1. Buat kernel dan representasi ABI-nya.
  2. Menganalisis perbedaan ABI antara build dan referensi.
  3. Perbarui representasi ABI (jika diperlukan).
  4. Menggunakan daftar simbol.

Petunjuk berikut berfungsi untuk kernel yang dapat Anda build menggunakan toolchain yang didukung (seperti toolchain Clang bawaan). repo manifests tersedia untuk semua cabang kernel umum Android dan untuk beberapa kernel khusus perangkat, yang memastikan bahwa toolchain yang benar digunakan saat Anda mem-build distribusi kernel untuk analisis.

Daftar simbol

KMI tidak menyertakan semua simbol dalam kernel atau bahkan semua dari lebih dari 30.000 simbol yang diekspor. Sebagai gantinya, simbol yang dapat digunakan oleh modul vendor diperinci secara eksplisit dalam kumpulan file daftar simbol yang dikelola secara publik di root hierarki kernel. Gabungan semua simbol dalam semua file daftar simbol menentukan kumpulan simbol KMI yang dipertahankan agar stabil. Contoh file daftar simbol adalah abi_gki_aarch64_db845c, yang mendeklarasikan simbol yang diperlukan untuk DragonBoard 845c.

Hanya simbol yang tercantum dalam daftar simbol serta struktur dan definisi terkait yang dianggap sebagai bagian dari KMI. Anda dapat memposting perubahan pada daftar simbol jika simbol yang Anda butuhkan tidak ada. Setelah ada dalam daftar simbol, dan merupakan bagian dari deskripsi KMI, antarmuka baru akan dipelihara sebagai stabil dan tidak boleh dihapus dari daftar simbol atau diubah setelah cabang dibekukan.

Setiap cabang kernel KMI Common Kernel Android (ACK) memiliki kumpulan daftar simbolnya sendiri. Tidak ada upaya untuk memberikan stabilitas ABI di 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 yang harus dipantau untuk stabilitas. Daftar simbol utama berisi simbol yang diperlukan oleh modul kernel GKI. Vendor diharapkan untuk mengirimkan dan memperbarui daftar simbol tambahan untuk memastikan bahwa antarmuka yang mereka andalkan mempertahankan 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 bertingkat.

Ketika KMI dibekukan, tidak ada perubahan yang diizinkan pada antarmuka KMI yang sudah ada karena mereka stabil. Namun, vendor bebas menambahkan simbol ke KMI kapan saja asalkan penambahan tidak memengaruhi stabilitas ABI yang ada. Simbol yang baru ditambahkan akan dipertahankan agar stabil segera setelah dicantumkan dalam daftar simbol KMI. Simbol tidak boleh dihapus dari daftar untuk kernel kecuali jika dapat dikonfirmasi bahwa tidak ada perangkat yang pernah dikirim dengan dependensi pada simbol tersebut.

Anda dapat membuat daftar simbol KMI untuk perangkat menggunakan petunjuk dari Cara bekerja dengan daftar simbol. Banyak partner mengirimkan satu daftar simbol per ACK, tetapi ini bukan persyaratan yang sulit. Jika membantu pemeliharaan, Anda dapat mengirimkan beberapa daftar simbol.

Memperluas KMI

Meskipun simbol KMI dan struktur terkait dipertahankan agar stabil (artinya perubahan yang merusak antarmuka stabil dalam kernel dengan KMI yang dibekukan tidak dapat diterima), kernel GKI tetap terbuka untuk ekstensi sehingga perangkat yang dikirimkan nanti pada tahun ini tidak perlu menentukan semua dependensinya sebelum KMI dibekukan. Untuk memperluas KMI, Anda dapat menambahkan simbol baru ke KMI untuk fungsi kernel yang diekspor baru atau yang sudah ada, meskipun KMI dibekukan. Patch kernel baru juga dapat diterima jika tidak merusak KMI.

Tentang kerusakan KMI

Kernel memiliki sumber dan biner dibuat dari sumber tersebut. Cabang kernel yang dipantau ABI menyertakan representasi ABI dari ABI GKI saat ini (dalam bentuk file .stg). Setelah biner (vmlinux, Image, dan modul GKI apa pun) di-build, representasi ABI dapat diekstrak dari biner. Setiap perubahan yang dilakukan pada file sumber kernel dapat memengaruhi biner dan juga memengaruhi .stg yang diekstrak. Penganalisis AbiAnalyzer membandingkan file .stg yang di-commit dengan file yang diekstrak dari artefak build dan menetapkan label Lint-1 pada perubahan di Gerrit jika menemukan perbedaan semantik.

Menangani kerusakan ABI

Sebagai contoh, patch berikut menyebabkan kerusakan ABI yang sangat jelas:

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.

Saat Anda menjalankan ABI build dengan patch ini diterapkan, alat akan keluar dengan kode error non-nol dan melaporkan perbedaan ABI yang mirip dengan ini:

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

Perbedaan ABI terdeteksi pada waktu build

Alasan error yang paling umum adalah saat pengemudi menggunakan simbol baru dari kernel yang tidak ada dalam daftar simbol mana pun.

Jika simbol tidak disertakan dalam daftar simbol (android/abi_gki_aarch64), Anda harus memverifikasi terlebih dahulu bahwa simbol diekspor dengan EXPORT_SYMBOL_GPL(symbol_name), lalu memperbarui representasi XML dan daftar simbol ABI. Misalnya, perubahan berikut menambahkan fitur Incremental FS baru ke cabang android-12-5.10, yang menyertakan pembaruan daftar simbol dan representasi XML ABI.

Jika simbol diekspor (baik oleh Anda maupun sebelumnya diekspor), tetapi tidak ada driver lain yang menggunakannya, Anda mungkin mendapatkan error 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 (lihat Memperbarui representasi ABI). Untuk contoh pembaruan XML ABI dan daftar simbol di ACK, lihat aosp/1367601.

Mengatasi kerusakan ABI kernel

Anda dapat menangani kerusakan ABI kernel dengan memfaktorkan ulang kode agar tidak mengubah ABI atau memperbarui representasi ABI. Gunakan diagram berikut untuk menentukan pendekatan terbaik untuk situasi Anda.

Diagram Alir Kerusakan ABI

Gambar 1. Penyelesaian kerusakan ABI

Memfaktorkan ulang kode untuk menghindari perubahan ABI

Lakukan segala upaya untuk menghindari perubahan ABI yang ada. Dalam banyak kasus, Anda dapat memfaktorkan ulang kode untuk menghapus perubahan yang memengaruhi ABI.

  • Memfaktorkan ulang perubahan kolom struct. Jika perubahan mengubah ABI untuk fitur debug, tambahkan #ifdef di sekitar kolom (dalam struct dan referensi sumber) dan pastikan CONFIG yang digunakan untuk #ifdef dinonaktifkan untuk defconfig produksi dan gki_defconfig. Untuk contoh cara konfigurasi debug dapat ditambahkan ke struct tanpa merusak ABI, lihat patchset ini.

  • Memfaktorkan ulang fitur agar tidak mengubah kernel inti. Jika fitur baru perlu ditambahkan ke ACK untuk mendukung modul partner, coba faktorkan ulang bagian perubahan ABI untuk menghindari perubahan ABI kernel. Untuk contoh penggunaan ABI kernel yang ada guna memberikan kemampuan tambahan tanpa mengubah ABI kernel, lihat Keadilan/1312213.

Memperbaiki ABI yang rusak di Android Gerrit

Jika tidak sengaja merusak ABI kernel, Anda perlu menyelidiki, menggunakan panduan yang diberikan oleh alat pemantauan ABI. Penyebab kerusakan yang paling umum adalah perubahan struktur data dan perubahan CRC simbol terkait, atau karena perubahan opsi konfigurasi yang menyebabkan salah satu hal yang disebutkan di atas. Mulailah dengan mengatasi masalah yang ditemukan oleh alat ini.

Anda dapat mereproduksi temuan ABI secara lokal, lihat Mem-build kernel dan representasi ABI-nya.

Tentang label Lint-1

Jika Anda mengupload perubahan ke cabang yang berisi KMI yang dibekukan atau diselesaikan, perubahan tersebut harus lulus AbiAnalyzer untuk memastikan perubahan tidak memengaruhi ABI stabil dengan cara yang tidak kompatibel. Selama proses ini, AbiAnalyzer akan mencari laporan ABI yang dibuat selama build (build yang diperluas yang melakukan build normal, lalu beberapa langkah ekstraksi dan perbandingan ABI.

Jika AbiAnalyzer menemukan laporan yang tidak kosong, laporan tersebut akan menetapkan label Lint-1 dan perubahan akan diblokir dari pengiriman hingga terselesaikan; hingga set patch menerima label Lint+1.

Memperbarui ABI kernel

Jika tidak dapat menghindari perubahan ABI, Anda harus menerapkan perubahan kode, representasi ABI, dan daftar simbol ke ACK. Agar Lint menghapus -1 dan tidak merusak kompatibilitas GKI, ikuti langkah-langkah berikut:

  1. Upload perubahan kode ke ACK.

  2. Tunggu hingga Anda menerima Code-Review +2 untuk patchset.

  3. Perbarui representasi ABI referensi.

  4. Gabungkan perubahan kode Anda dan perubahan update ABI.

Mengupload perubahan kode ABI ke ACK

Pembaruan ABI ACK bergantung pada jenis perubahan yang dilakukan.

  • Jika perubahan ABI terkait dengan fitur yang memengaruhi pengujian CTS atau VTS, perubahan tersebut biasanya dapat dipilih untuk ACK apa adanya. Misalnya:

  • Jika perubahan ABI ditujukan untuk fitur yang dapat dibagikan ke ACK, perubahan tersebut dapat dipilih menjadi ACK sebagaimana adanya. Misalnya, perubahan berikut tidak diperlukan untuk pengujian CTS atau VTS, tetapi dapat dibagikan dengan ACK:

  • Jika perubahan ABI memperkenalkan fitur baru yang tidak perlu disertakan dalam ACK, Anda dapat memperkenalkan simbol ke ACK menggunakan stub seperti yang dijelaskan di bagian berikut.

Menggunakan stub untuk ACK

Stub hanya diperlukan untuk perubahan kernel inti yang tidak menguntungkan ACK, seperti perubahan performa dan daya. Daftar berikut menjelaskan contoh stub dan pilihan sebagian di ACK untuk GKI.

  • Core-isolate stub fitur (AOSP/1284493). Kemampuan di ACK tidak diperlukan, tetapi simbol harus ada di ACK agar modul Anda dapat menggunakan simbol ini.

  • Simbol placeholder untuk modul vendor (aosp/1288860).

  • Pilihan khusus ABI untuk fitur pelacakan peristiwa mm per proses (AOSP/1288454). Patch asli dipilih untuk ACK, lalu dipangkas agar hanya menyertakan perubahan yang diperlukan untuk menyelesaikan perbedaan ABI untuk task_struct dan mm_event_count. Patch ini juga mengupdate enum mm_event_type untuk berisi anggota akhir.

  • Pemilihan sebagian perubahan ABI struktur termal yang memerlukan lebih dari sekadar menambahkan kolom ABI baru.

    • Patch aosp/1255544 menyelesaikan perbedaan ABI antara kernel partner dan ACK.

    • Patch AOS/1291018 memperbaiki masalah fungsional yang ditemukan selama pengujian GKI pada patch sebelumnya. Perbaikan ini mencakup inisialisasi 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, sehingga partner dapat menyertakan CONFIG_NL80211_TESTMODE dalam kernel produksi mereka dan tetap mempertahankan kepatuhan GKI.

Menerapkan KMI saat runtime

Kernel GKI menggunakan opsi konfigurasi 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 simbol yang tercantum dalam daftar simbol. Semua simbol lainnya tidak diekspor, dan pemuatan modul yang memerlukan simbol yang tidak diekspor akan ditolak. Pembatasan ini diterapkan pada waktu build dan entri yang tidak ada akan 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.

Menerapkan KMI menggunakan pembuatan versi modul

Kernel Image Kernel Generik (GKI) menggunakan pembuatan versi modul (CONFIG_MODVERSIONS) sebagai tindakan tambahan untuk menegakkan kepatuhan KMI saat runtime. Pembuatan versi modul dapat menyebabkan kegagalan ketidakcocokan cyclic redundancy check (CRC) saat waktu pemuatan modul jika KMI yang diharapkan dari modul tidak cocok dengan KMI vmlinux. Misalnya, berikut adalah kegagalan umum yang terjadi pada waktu pemuatan 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 pembuatan versi modul

Pembuatan versi modul berguna karena alasan berikut:

  • Pembuatan versi modul menangkap perubahan pada visibilitas struktur data. Jika modul mengubah struktur data buram, yaitu struktur data yang bukan bagian dari KMI, modul akan rusak setelah perubahan struktur di masa mendatang.

    Sebagai contoh, pertimbangkan kolom fwnode di struct device. Kolom ini HARUS buram untuk modul sehingga tidak dapat membuat perubahan pada kolom device->fw_node atau membuat asumsi tentang ukurannya.

    Namun, jika modul menyertakan <linux/fwnode.h> (langsung atau tidak langsung), kolom fwnode di struct device tidak lagi buram. Modul kemudian dapat membuat perubahan pada device->fwnode->dev atau device->fwnode->ops. Skenario ini bermasalah karena beberapa alasan, yang dinyatakan sebagai berikut:

    • Fungsi ini dapat merusak asumsi yang dibuat oleh kode kernel inti tentang struktur data internalnya.

    • Jika update kernel mendatang mengubah struct fwnode_handle (jenis data fwnode), modul tidak akan lagi berfungsi dengan kernel baru. Selain itu, stgdiff tidak akan menampilkan perbedaan apa pun karena modul merusak 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 saat dimuat pada lain waktu oleh kernel baru yang tidak kompatibel. Pembuatan versi modul menambahkan pemeriksaan run-time untuk menghindari pemuatan modul yang tidak kompatibel dengan KMI kernel secara tidak sengaja. Pemeriksaan ini mencegah masalah runtime yang sulit di-debug dan error kernel yang mungkin terjadi akibat ketidakcocokan yang tidak terdeteksi di KMI.

Mengaktifkan pembuatan versi modul akan mencegah semua masalah ini.

Memeriksa ketidakcocokan CRC tanpa mem-booting perangkat

stgdiff membandingkan dan melaporkan ketidakcocokan CRC antara kernel beserta perbedaan ABI lainnya.

Selain itu, build kernel lengkap dengan CONFIG_MODVERSIONS yang diaktifkan akan 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, namespace 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 tersebut digunakan oleh salah satu modul yang Anda muat di perangkat, modul tersebut tidak akan dimuat.

Jika tidak memiliki semua artefak build, tetapi memiliki file vmlinux kernel GKI dan kernel, Anda dapat membandingkan nilai CRC untuk simbol tertentu dengan menjalankan perintah berikut pada kernel dan membandingkan outputnya:

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

Menyelesaikan ketidakcocokan CRC

Gunakan langkah-langkah berikut untuk mengatasi ketidakcocokan CRC saat memuat modul:

  1. Bangun kernel GKI dan kernel perangkat Anda menggunakan opsi --kbuild_symtypes seperti yang ditunjukkan dalam perintah berikut:

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

    Perintah ini menghasilkan file .symtypes untuk setiap file .o. Lihat KBUILD_SYMTYPES di Kleaf untuk mengetahui detailnya.

    Untuk Android 13 dan yang lebih lama, build kernel GKI dan kernel perangkat Anda dengan menambahkan KBUILD_SYMTYPES=1 ke perintah yang Anda gunakan untuk membangun kernel, seperti yang ditunjukkan dalam perintah berikut:

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

    Saat menggunakan build_abi.sh,, flag KBUILD_SYMTYPES=1 secara implisit sudah ditetapkan.

  2. Temukan file .c tempat simbol dengan ketidakcocokan CRC diekspor, menggunakan perintah berikut:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
    
  3. 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 adalah karakteristik file .c:

    • Format file .c adalah satu baris (yang berpotensi sangat panjang) per simbol.

    • [s|u|e|etc]# di awal baris berarti simbol tersebut memiliki jenis data [struct|union|enum|etc]. Contoh:

      t#bool typedef _Bool bool
      
    • Awalan # yang tidak ada di awal baris menunjukkan bahwa simbol adalah fungsi. Contoh:

      find_module s#module * find_module ( const char * )
      
  4. Bandingkan kedua file dan perbaiki semua perbedaan.

Kasus 1: Perbedaan karena visibilitas jenis data

Jika satu kernel menyimpan simbol atau jenis data yang buram untuk modul dan kernel lainnya tidak, perbedaan tersebut akan muncul di antara file .symtypes dari dua kernel. File .symtypes dari salah satu kernel memiliki UNKNOWN untuk simbol dan file .symtypes dari kernel lainnya memiliki tampilan yang diperluas dari simbol atau jenis data.

Misalnya, menambahkan baris berikut ke file include/linux/device.h di kernel Anda akan menyebabkan ketidakcocokan CRC, salah satunya adalah untuk module_layout():

 #include <linux/fwnode.h>

Membandingkan module.symtypes untuk simbol tersebut, akan menampilkan 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), gabungkan Android Common Kernel terbaru ke dalam kernel Anda sehingga Anda menggunakan basis kernel GKI terbaru.

Umumnya, kernel GKI memiliki nilai UNKNOWN, tetapi kernel Anda memiliki detail internal simbol karena perubahan yang dibuat pada kernel Anda. Hal ini dikarenakan salah satu file dalam kernel Anda menambahkan #include yang tidak ada dalam kernel GKI.

Sering kali, perbaikannya hanya menyembunyikan #include baru dari genksyms.

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

Atau, untuk mengidentifikasi #include yang menyebabkan perbedaan, ikuti langkah-langkah berikut:

  1. Buka file header yang menentukan simbol atau jenis data yang memiliki perbedaan ini. Misalnya, edit include/linux/fwnode.h untuk struct fwnode_handle.

  2. Tambahkan kode berikut di bagian atas file header:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. Dalam file .c modul yang memiliki ketidakcocokan CRC, tambahkan baris berikut sebagai baris pertama sebelum baris #include.

    #define CRC_CATCH 1
    
  4. Kompilasi modul Anda. Error waktu build yang dihasilkan menunjukkan rantai file header #include yang menyebabkan ketidakcocokan CRC ini. 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 link dalam rantai #include ini disebabkan oleh perubahan yang dilakukan di kernel Anda, yang tidak ada di kernel GKI.

  5. Identifikasi perubahan, kembalikan ke kernel Anda, atau upload ke ACK dan gabungkan.

Kasus 2: Perbedaan karena perubahan jenis data

Jika ketidakcocokan CRC untuk simbol atau jenis data bukan karena perbedaan visibilitas, hal itu disebabkan oleh perubahan aktual (penambahan, penghapusan, atau perubahan) dalam jenis data itu sendiri.

Misalnya, membuat perubahan berikut di kernel akan 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 tersebut, tampilannya mungkin 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:

  1. Temukan definisi simbol dalam kode sumber (biasanya dalam file .h).

    • Untuk perbedaan simbol antara kernel Anda dan kernel GKI, temukan commit dengan menjalankan perintah berikut:
    git blame
    
    • Untuk simbol yang dihapus (saat simbol dihapus dalam hierarki dan Anda juga ingin menghapusnya di hierarki lain), Anda perlu menemukan perubahan yang menghapus baris. Gunakan perintah berikut pada hierarki tempat baris dihapus:
    git log -S "copy paste of deleted line/word" -- <file where it was deleted>
    
  2. Tinjau daftar commit yang ditampilkan untuk menemukan perubahan atau penghapusan. Commit pertama mungkin adalah yang Anda telusuri. Jika tidak, lihat daftar hingga Anda menemukan commit.

  3. Setelah mengidentifikasi perubahan, kembalikan ke kernel atau upload ke ACK dan gabungkan.