Monitoraggio dell'ABI del kernel di Android

Puoi utilizzare gli strumenti di monitoraggio dell'interfaccia a oggetti di applicazioni (ABI), disponibili in Android 11 e versioni successive, per stabilizzare l'ABI in-kernel dei kernel Android. Lo strumento raccoglie e confronta le rappresentazioni ABI dai binari del kernel esistenti (vmlinux+ moduli GKI). Queste rappresentazioni ABI sono i file .stg e gli elenchi di simboli. L'interfaccia su cui la rappresentazione fornisce una visualizzazione è chiamata Kernel Module Interface (KMI). Puoi utilizzare gli strumenti per monitorare e mitigare le modifiche al KMI.

Gli strumenti di monitoraggio ABI sono sviluppati in AOSP e utilizzano STG (o libabigail in Android 13 e versioni precedenti) per generare e confrontare le rappresentazioni.

Questa pagina descrive gli strumenti, la procedura di raccolta e analisi delle rappresentazioni ABI e l'utilizzo di queste rappresentazioni per garantire la stabilità dell'ABI in-kernel. Questa pagina fornisce anche informazioni per apportare modifiche ai kernel Android.

Procedura

L'analisi dell'ABI del kernel richiede più passaggi, la maggior parte dei quali può essere automatizzata:

  1. Compila il kernel e la relativa rappresentazione ABI.
  2. Analizza le differenze ABI tra la build e un riferimento.
  3. Aggiorna la rappresentazione ABI (se richiesta).
  4. Lavorare con gli elenchi di simboli.

Le seguenti istruzioni sono valide per qualsiasi kernel che puoi compilare utilizzando una toolchain supportata (ad esempio la toolchain Clang precompilata). repo manifests sono disponibili per tutti i rami del kernel comune di Android e per diversi kernel specifici del dispositivo. Garantiscono che venga utilizzata la toolchain corretta quando crei una distribuzione del kernel per l'analisi.

Elenchi di simboli

Il KMI non include tutti i simboli del kernel o anche tutti i più di 30.000 simboli esportati. I simboli che possono essere utilizzati dai moduli del fornitore sono invece elencati esplicitamente in un insieme di file di elenchi di simboli gestiti pubblicamente nella struttura ad albero del kernel (gki/{ARCH}/symbols/* o android/abi_gki_{ARCH}_* in Android 15 e versioni precedenti). L'unione di tutti i simboli in tutti i file dell'elenco di simboli definisce l'insieme di simboli KMI mantenuti stabili. Un file di elenco di simboli di esempio è gki/aarch64/symbols/db845c, che dichiara i simboli richiesti per DragonBoard 845c.

Solo i simboli elencati in un elenco di simboli e le relative strutture e definizioni sono considerati parte del KMI. Puoi pubblicare modifiche agli elenchi di simboli se quelli di cui hai bisogno non sono presenti. Una volta che le nuove interfacce sono in un elenco di simboli e fanno parte della descrizione del KMI, vengono mantenute stabili e non devono essere rimosse dall'elenco di simboli o modificate dopo il blocco del ramo.

Ogni ramo del kernel KMI di Android Common Kernel (ACK) ha il proprio insieme di elenchi di simboli. Non viene fatto alcun tentativo di garantire la stabilità dell'ABI tra i diversi branch del kernel KMI. Ad esempio, il KMI per android12-5.10 è completamente indipendente dal KMI per android13-5.10.

Gli strumenti ABI utilizzano gli elenchi di simboli KMI per limitare le interfacce da monitorare per la stabilitá. I fornitori devono inviare e aggiornare i propri elenchi di simboli per garantire che le interfacce su cui si basano mantengano la compatibilità ABI. Ad esempio, per visualizzare un elenco di elenchi di simboli per il kernel android16-6.12, consulta https://android.googlesource.com/kernel/common/+/refs/heads/android16-6.12/gki/aarch64/symbols

Un elenco di simboli contiene i simboli segnalati come necessari per il particolare fornitore o dispositivo. L'elenco completo utilizzato dagli strumenti è l'unione di tutti i file dell'elenco di simboli KMI. Gli strumenti ABI determinano i dettagli di ogni simbolo, tra cui la firma della funzione e le strutture di dati nidificate.

Quando il KMI è bloccato, non sono consentite modifiche alle interfacce KMI esistenti, poiché sono stabili. Tuttavia, i fornitori sono liberi di aggiungere simboli al KMI in qualsiasi momento purché le aggiunte non influiscano sulla stabilità dell'ABI esistente. I simboli appena aggiunti vengono mantenuti stabili non appena vengono citati da un elenco di simboli KMI. I simboli non devono essere rimossi da un elenco per un kernel, a meno che non sia possibile confermare che nessun dispositivo sia mai stato spedito con una dipendenza da quel simbolo.

Puoi generare un elenco di simboli KMI per un dispositivo seguendo le istruzioni riportate in Come utilizzare gli elenchi di simboli. Molti partner inviano un elenco di simboli per ACK, ma non si tratta di un requisito obbligatorio. Se ti è utile per la manutenzione, puoi inviare più elenchi di simboli.

Espandere il KMI

Sebbene i simboli KMI e le strutture correlate vengano mantenuti stabili (ovvero non possono essere accettate modifiche che rompono le interfacce stabili in un kernel con un KMI bloccato), il kernel GKI rimane aperto alle estensioni in modo che i dispositivi inviati in un secondo momento dell'anno non debbano definire tutte le dipendenze prima che il KMI venga bloccato. Per estendere il KMI, puoi aggiungere nuovi simboli per funzioni di kernel esportate nuove o esistenti, anche se il KMI è bloccato. Potrebbero essere accettate anche nuove patch del kernel se non compromettono il KMI.

Informazioni sui malfunzionamenti del KMI

Un kernel ha origini e i binari vengono compilati a partire da queste origini. I rami del kernel monitorati dall'ABI includono una rappresentazione ABI dell'ABI GKI corrente (sotto forma di file .stg). Dopo la compilazione dei binari (vmlinux, Image e eventuali moduli GKI), è possibile estrarre una rappresentazione ABI dai binari. Qualsiasi modifica apportata a un file sorgente del kernel può influire sui file binari e, a loro volta, anche sul .stg estratto. L'analizzatore AbiAnalyzer confronta il file .stg sottoposto a commit con quello estratto dagli elementi di build e imposta un'etichetta Lint-1 sulla modifica in Gerrit se rileva una differenza semantica.

Gestire i malfunzionamenti dell'ABI

Ad esempio, la patch seguente introduce un'interruzione ABI molto evidente:

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.

Quando esegui l'ABI di compilazione con questa patch applicata, lo strumento esce con un codice di errore diverso da zero e segnala una differenza ABI simile a questa:

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

Differenze ABI rilevate in fase di compilazione

La causa più comune degli errori si verifica quando un driver utilizza un nuovo simbolo del kernel che non è presente in nessuno degli elenchi di simboli.

Se il simbolo non è incluso nell'elenco dei simboli, devi prima verificare che sia esportato con EXPORT_SYMBOL_GPL(symbol_name) e poi aggiornare l'elenco dei simboli e la rappresentazione ABI. Ad esempio, le seguenti modifiche aggiungono la nuova funzionalità FS incrementale al ramo android-12-5.10, che include l'aggiornamento dell'elenco di simboli e della rappresentazione ABI.

  • L'esempio di modifica della funzionalità è in aosp/1345659.
  • L'esempio di elenco di simboli si trova in aosp/1346742.
  • L'esempio di modifica della rappresentazione dell'ABI è in aosp/1349377.

Se il simbolo è esportato (da te o è stato esportato in precedenza) ma nessun altro driver lo utilizza, potresti ricevere un errore di compilazione simile al seguente.

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

Per risolvere il problema, aggiorna l'elenco di simboli KMI sia nel kernel sia nell'ACK (consulta Aggiornare la rappresentazione ABI). Per un esempio di aggiornamento di un elenco di simboli e della rappresentazione ABI nell'ACK, consulta aosp/1367601.

Risolvere i problemi di interruzione dell'ABI del kernel

Puoi gestire le interruzioni dell'ABI del kernel ristrutturando il codice in modo da non modificare l'ABI o aggiornando la rappresentazione dell'ABI. Utilizza il seguente diagramma per determinare l'approccio migliore per la tua situazione.

Diagramma di flusso per l'interruzione dell'ABI

Figura 1. Risoluzione dei problemi relativi all'ABI

Ristrutturare il codice per evitare modifiche all'ABI

Fai del tuo meglio per evitare di modificare l'ABI esistente. In molti casi, puoi eseguire il refactoring del codice per rimuovere le modifiche che influiscono sull'ABI.

  • Modifiche al refactoring dei campi delle strutture. Se una modifica modifica l'ABI per una funzionalità di debug, aggiungi un #ifdef attorno ai campi (nelle strutture e nei riferimenti di origine) e assicurati che il CONFIG utilizzato per il #ifdef sia disattivato per il defconfig di produzione e gki_defconfig. Per un esempio di come una configurazione di debug può essere aggiunta a una struct senza violare l'ABI, consulta questo patchset.

  • Funzionalità di refactoring per non modificare il kernel di base. Se è necessario aggiungere nuove funzionalità ad ACK per supportare i moduli del partner, prova a eseguire il refactoring della parte dell'ABI della modifica per evitare di modificare l'ABI del kernel. Per un esempio di utilizzo dell'ABI del kernel esistente per aggiungere funzionalità aggiuntive senza modificare l'ABI del kernel, consulta aosp/1312213.

Correggere un ABI non funzionante su Android Gerrit

Se non hai violato intenzionalmente l'ABI del kernel, devi effettuare accertamenti utilizzando le indicazioni fornite dagli strumenti di monitoraggio dell'ABI. Le cause più comuni di interruzioni sono le modifiche alle strutture di dati e le modifiche al CRC del simbolo associato oppure le modifiche alle opzioni di configurazione che portano a una delle cause sopra indicate. Inizia risolvendo i problemi rilevati dallo strumento.

Puoi riprodurre i risultati ABI localmente, consulta Compilare il kernel e la relativa rappresentazione ABI.

Informazioni sulle etichette Lint-1

Se carichi modifiche in un ramo contenente un KMI congelato o finalizzato, le modifiche devono superare il controllo AbiAnalyzer per garantire che non influiscano sull'ABI stabile in modo incompatibile. Durante questa procedura, AbiAnalyzer cerca il report ABI creato durante la compilazione (una compilazione estesa che esegue la compilazione normale e poi alcuni passaggi di estrazione e confronto dell'ABI.

Se AbiAnalyzer trova un report non vuoto, imposta l'etichetta Lint-1 e l'invio della modifica viene bloccato fino alla risoluzione del problema o fino a quando il set di patch non riceve l'etichetta Lint+1.

Aggiornare l'ABI del kernel

Se la modifica dell'ABI è inevitabile, devi applicare le modifiche al codice, la rappresentazione dell'ABI e l'elenco di simboli all'ACK. Per fare in modo che Lint rimuova il -1 e non interrompa la compatibilità con GKI, segui questi passaggi:

  1. Carica le modifiche al codice nell'ACK.

  2. Attendi di ricevere una revisione del codice +2 per il set di patch.

  3. Aggiorna la rappresentazione dell'ABI di riferimento.

  4. Unisci le modifiche al codice e la modifica dell'aggiornamento dell'ABI.

Carica le modifiche al codice ABI nell'ACK

L'aggiornamento dell'ABI ACK dipende dal tipo di modifica apportata.

  • Se una modifica dell'ABI è correlata a una funzionalità che influisce sui test CTS o VTS, la modifica può in genere essere selezionata per l'ACK così com'è. Ad esempio:

    • aosp/1289677 è necessario per il funzionamento dell'audio.
    • aosp/1295945 è necessario per il funzionamento della porta USB.
  • Se una modifica dell'ABI riguarda una funzionalità che può essere condivisa con l'ACK, la modifica può essere selezionata per l'ACK così com'è. Ad esempio, le seguenti modifiche non sono necessarie per il test CTS o VTS, ma possono essere condivise con l'ACK:

  • Se una modifica dell'ABI introduce una nuova funzionalità che non deve essere inclusa nell'ACK, puoi introdurre i simboli nell'ACK utilizzando uno stub come descritto nella sezione seguente.

Utilizzare stub per ACK

Gli stub devono essere necessari solo per le modifiche al kernel di base che non apportano vantaggi all'ACK, ad esempio le modifiche al rendimento e alla potenza. L'elenco seguente illustra esempi di stub e cherry-pick parziali in ACK per GKI.

  • Stub della funzionalità di isolamento principale (aosp/1284493). Le funzionalità in ACK non sono necessarie, ma i simboli devono essere presenti in ACK affinché i tuoi moduli possano utilizzarli.

  • Simbolo segnaposto per il modulo del fornitore (aosp/1288860).

  • Scelta accurata della funzionalità di monitoraggio degli eventi mm per processo solo per ABI (aosp/1288454). La patch originale è stata selezionata per ACK e poi tagliata in modo da includere solo le modifiche necessarie per risolvere la differenza ABI per task_struct e mm_event_count. Questa patch aggiorna anche l'enum mm_event_type in modo da includere gli elementi finali.

  • Scelta parziale delle modifiche dell'ABI della struttura termica che richiedevano più dell'aggiunta dei nuovi campi ABI.

    • La patch aosp/1255544 ha risolto le differenze ABI tra il kernel del partner e l'ACK.

    • La patch aosp/1291018 ha risolto i problemi funzionali rilevati durante i test GKI della patch precedente. La correzione ha incluso l'inizializzazione della struttura del parametro del sensore per registrare più zone termiche su un singolo sensore.

  • CONFIG_NL80211_TESTMODE Modifiche all'ABI (aosp/1344321). Questa patch ha aggiunto le modifiche necessarie alla struttura per l'ABI e ha garantito che i campi aggiuntivi non causassero differenze funzionali, consentendo ai partner di includere CONFIG_NL80211_TESTMODE nei kernel di produzione e di mantenere la conformità GKI.

Applicare il KMI in fase di runtime

I kernel GKI utilizzano le opzioni di configurazione TRIM_UNUSED_KSYMS=y e UNUSED_KSYMS_WHITELIST=<union of all symbol lists>, che limitano i simboli esportati (ad esempio i simboli esportati utilizzando EXPORT_SYMBOL_GPL()) a quelli elencati in un elenco di simboli. Tutti gli altri simboli non vengono esportati e il caricamento di un modulo che richiede un simbolo non esportato viene negato. Questa limitazione viene applicata in fase di compilazione e le voci mancanti vengono segnalate.

Per scopi di sviluppo, puoi utilizzare una build del kernel GKI che non include il trimming dei simboli (ovvero è possibile utilizzare tutti i simboli di solito esportati). Per individuare queste build, cerca le build kernel_debug_aarch64 su ci.android.com.

Applica il KMI utilizzando il controllo delle versioni dei moduli

I kernel dell'immagine del kernel generico (GKI) utilizzano il controllo della versione dei moduli (CONFIG_MODVERSIONS) come misura aggiuntiva per applicare la conformità del KMI al runtime. La gestione delle versioni dei moduli può causare errori di mancata corrispondenza del controllo di ridondanza ciclica (CRC) al momento del caricamento del modulo se il KMI previsto di un modulo non corrisponde al KMIvmlinux. Ad esempio, di seguito è riportato un errore tipico che si verifica al caricamento del modulo a causa di una mancata corrispondenza del CRC per il simbolo 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 ''

Utilizzi del controllo delle versioni dei moduli

Il controllo delle versioni dei moduli è utile per i seguenti motivi:

  • La gestione delle versioni dei moduli rileva le modifiche alla visibilità della struttura dei dati. Se i moduli cambiano strutture di dati opache, ovvero strutture di dati che non fanno parte del KMI, non funzionano più dopo le modifiche future alla struttura.

    Ad esempio, considera il campo fwnode in struct device. Questo campo DEVE essere opaco per i moduli in modo che non possano apportare modifiche ai campi di device->fw_node o fare supposizioni sulle relative dimensioni.

    Tuttavia, se un modulo include <linux/fwnode.h> (direttamente o indirettamente), il campo fwnode in struct device non è più opaco per questo. Il modulo può quindi apportare modifiche a device->fwnode->dev o device->fwnode->ops. Questo scenario è problematico per diversi motivi, elencati di seguito:

    • Può violare le ipotesi fatte dal codice del kernel di base sulle sue strutture di dati interne.

    • Se un aggiornamento futuro del kernel modifica il struct fwnode_handle (il tipo di dato di fwnode), il modulo non funziona più con il nuovo kernel. Inoltre, stgdiff non mostrerà differenze perché il modulo viola il KMI manipolando direttamente le strutture di dati interne in modi che non possono essere rilevati solo ispezionando la rappresentazione binaria.

  • Un modulo attuale è considerato incompatibile con KMI quando viene caricato in un secondo momento da un nuovo kernel incompatibile. La gestione delle versioni dei moduli aggiunge un controllo di runtime per evitare di caricare accidentalmente un modulo non compatibile con KMI con il kernel. Questo controllo evita problemi di runtime difficili da eseguire il debug e arresti anomali del kernel che potrebbero essere causati da un'incompatibilità non rilevata nel KMI.

L'attivazione del controllo delle versioni dei moduli evita tutti questi problemi.

Verificare la presenza di mancate corrispondenze CRC senza avviare il dispositivo

stgdiff confronta e segnala le mancate corrispondenze CRC tra i kernel, nonché altre differenze ABI.

Inoltre, una compilazione completa del kernel con CONFIG_MODVERSIONS abilitato genera un Module.symvers file nell'ambito della normale procedura di compilazione. Questo file contiene una riga per ogni simbolo esportato dal kernel (vmlinux) e dai moduli. Ogni riga è composta dal valore CRC, dal nome del simbolo, dallo spazio dei nomi del simbolo, dal nome del vmlinux o del modulo che esporta il simbolo e dal tipo di esportazione (ad esempio, EXPORT_SYMBOL rispetto a EXPORT_SYMBOL_GPL).

Puoi confrontare i file Module.symvers della build GKI con quelli della tua build per verificare la presenza di eventuali differenze CRC nei simboli esportati da vmlinux. Se esiste una differenza di valore CRC in un simbolo esportato da vmlinux e quel simbolo viene utilizzato da uno dei moduli caricati nel dispositivo, il modulo non viene caricato.

Se non disponi di tutti gli elementi di compilazione, ma hai i file vmlinux del kernel GKI e del tuo kernel, puoi confrontare i valori CRC per un simbolo specifico eseguendo il seguente comando su entrambi i kernel e confrontando l'output:

nm <path to vmlinux>/vmlinux | grep __crc_<symbol name>

Ad esempio, il seguente comando controlla il valore CRC per il simbolo module_layout:

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

Risolvere le mancate corrispondenze CRC

Per risolvere una mancata corrispondenza del CRC durante il caricamento di un modulo:

  1. Compila il kernel GKI e il kernel del dispositivo utilizzando l'opzione --kbuild_symtypes come mostrato nel seguente comando:

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

    Questo comando genera un file .symtypes per ogni file .o. Per maggiori dettagli, consulta KBUILD_SYMTYPES in Kleaf.

    Per Android 13 e versioni precedenti, compila il kernel GKI e il kernel del dispositivo anteponendo KBUILD_SYMTYPES=1 al comando utilizzato per compilare il kernel, come mostrato nel seguente comando:

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

    Quando utilizzi build_abi.sh,, il flag KBUILD_SYMTYPES=1 è già impostato implicitamente.

  2. Trova il file .c in cui è esportato il simbolo con mancata corrispondenza CRC utilizzando il seguente comando:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
  3. Il file .c ha un file .symtypes corrispondente nel GKI e negli elementi di compilazione del kernel del dispositivo. Individua il file .c utilizzando i seguenti comandi:

    cd out/$BRANCH/common && ls -1 kernel/module.*
    kernel/module.o
    kernel/module.o.symversions
    kernel/module.symtypes

    Di seguito sono riportate le caratteristiche del file .c:

    • Il formato del file .c è una riga (potenzialmente molto lunga) per simbolo.

    • [s|u|e|etc]# all'inizio della riga indica che il simbolo è di tipo di dati [struct|union|enum|etc]. Ad esempio:

      t#bool typedef _Bool bool
      
    • Un prefisso # mancante all'inizio della riga indica che il simbolo è una funzione. Ad esempio:

      find_module s#module * find_module ( const char * )
      
  4. Confronta i due file e correggi tutte le differenze.

Caso 1: differenze dovute alla visibilità del tipo di dati

Se un kernel mantiene un simbolo o un tipo di dati opaco per i moduli e l'altro no, questa differenza viene visualizzata tra i file .symtypes dei due kernel. Il file .symtypes di uno dei kernel contiene UNKNOWN per un simbolo e il file .symtypes dell'altro kernel contiene una vista espansa del simbolo o del tipo di dati.

Ad esempio, l'aggiunta della seguente riga al file include/linux/device.h nel kernel causa mancate corrispondenze CRC, una delle quali è per module_layout():

 #include <linux/fwnode.h>

Il confronto del module.symtypes per quel simbolo mette in evidenza le seguenti differenze:

 $ 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 ] ; }
  ...

Se il kernel ha un valore UNKNOWN e il kernel GKI ha la visualizzazione espansa del simbolo (molto improbabile), unisci il kernel Android Common più recente al tuo kernel in modo da utilizzare la base del kernel GKI più recente.

Nella maggior parte dei casi, il kernel GKI ha un valore UNKNOWN, ma il kernel ha i dettagli interni del simbolo a causa delle modifiche apportate al kernel. Questo accade perché uno dei file del kernel ha aggiunto un #include non presente nel kernel GKI.

Spesso, la soluzione è semplicemente nascondere il nuovo #include da genksyms.

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

In caso contrario, per identificare il #include che causa la differenza, segui questi passaggi:

  1. Apri il file di intestazione che definisce il simbolo o il tipo di dati con questa differenza. Ad esempio, modifica include/linux/fwnode.h per il struct fwnode_handle.

  2. Aggiungi il seguente codice all'inizio del file di intestazione:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. Nel file .c del modulo con una mancata corrispondenza CRC, aggiungi quanto segue come prima riga prima di qualsiasi riga #include.

    #define CRC_CATCH 1
    
  4. Compila il modulo. L'errore di compilazione risultante mostra la catena di file di intestazione #include che ha causato questa mancata corrispondenza del CRC. Ad esempio:

    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"
    

    Uno dei link di questa catena di #include è dovuto a una modifica apportata al kernel che non è presente nel kernel GKI.

  5. Identifica la modifica, ripristinala nel kernel o caricala su ACK e fai in modo che venga unita.

Caso 2: differenze dovute a modifiche del tipo di dati

Se la mancata corrispondenza CRC per un simbolo o un tipo di dati non è dovuta a una differenza di visibilità, è dovuta a modifiche effettive (aggiunte, rimozioni o modifiche) nel tipo di dati stesso.

Ad esempio, apportare la seguente modifica al kernel causa diversi mancata corrispondenza del CRC poiché molti simboli sono indirettamente interessati da questo tipo di modifica:

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);

Un mancato accoppiamento CRC riguarda devm_of_platform_populate().

Se confronti i file .symtypes per quel simbolo, potresti visualizzare il seguente messaggio:

 $ 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 * ) ; ...

Per identificare il tipo modificato:

  1. Trova la definizione del simbolo nel codice sorgente (di solito nei file .h).

    • Per le differenze nei simboli tra il kernel e il kernel GKI, trovate il commit eseguendo il seguente comando:
    git blame
    • Per i simboli eliminati (se un simbolo viene eliminato in un albero e vuoi eliminarlo anche nell'altro albero), devi trovare la modifica che ha eliminato la riga. Utilizza il seguente comando sull'albero in cui è stata eliminata la riga:
    git log -S "copy paste of deleted line/word" -- <file where it was deleted>
  2. Esamina l'elenco dei commit restituiti per individuare la modifica o l'eliminazione. Probabilmente il primo commit è quello che stai cercando. In caso contrario, scorri l'elenco fino a trovare il commit.

  3. Dopo aver identificato la modifica, ripristinala nel kernel o caricala su ACK e fai in modo che venga unita.