Monitoraggio ABI del kernel Android

È possibile utilizzare gli strumenti di monitoraggio dell'interfaccia binaria (ABI) dell'applicazione, disponibili in Android 11 e versioni successive, per stabilizzare l'ABI nel kernel dei kernel Android. Le raccoglie utensili e mette a confronto le rappresentazioni ABI dai binari del kernel esistenti ( vmlinux + moduli). Queste rappresentazioni sono i ABI .xml file e le liste dei simboli. L'interfaccia su cui la rappresentazione fornisce una vista è chiamata Kernel Module Interfaces (KMI). È possibile utilizzare gli strumenti per tenere traccia e mitigare le modifiche al KMI.

Il monitoraggio utensili ABI è sviluppato in AOSP e usi libabigail per generare e confrontare le rappresentazioni.

Questa pagina descrive gli strumenti, il processo di raccolta e analisi delle rappresentazioni ABI e l'uso di tali rappresentazioni per fornire stabilità all'ABI nel kernel. Questa pagina fornisce anche informazioni per apportare modifiche ai kernel Android.

Questa directory contiene gli strumenti specifici per l'analisi ABI. Usatelo con gli script di build forniti da build_abi.sh .)

Processi

L'analisi dell'ABI del kernel richiede più passaggi, molti dei quali possono essere automatizzati:

  1. Acquisire la toolchain, script di build, e sorgenti del kernel attraverso repo .
  2. Fornire eventuali prerequisiti (come il libabigail biblioteca e raccolta di strumenti).
  3. Costruire il kernel e la sua rappresentazione ABI .
  4. Analizzare le differenze tra ABI la costruzione e un riferimento .
  5. Aggiornare la rappresentazione ABI (se necessario) .
  6. Lavora con liste dei simboli .

Le seguenti istruzioni di lavoro per qualsiasi kernel che si può costruire con un toolchain supportato (ad esempio la precompilati Clang toolchain). repo manifests sono disponibili per tutti i rami comuni del kernel Android e per diversi kernel dispositivi specifici, si assicurano che la toolchain corretto viene utilizzato quando si genera una distribuzione kernel per l'analisi.

Utilizzo degli strumenti di monitoraggio ABI

1. Acquisire la toolchain, creare script e sorgenti del kernel tramite repository

È possibile acquisire il toolchain, script di build (questi script), e sorgenti del kernel con repo . Per la documentazione dettagliata, consultare le corrispondenti informazioni per compilare un kernel Android .

Per illustrare il processo, le seguenti operazioni utilizzano common-android12-5.10 , un ramo del kernel di Android, che è l'ultimo kernel GKI rilasciato al momento in cui scriviamo. Per ottenere questo ramo attraverso repo , eseguire il seguente:

repo init -u https://android.googlesource.com/kernel/manifest -b common-android12-5.10
repo sync

2. Fornire i prerequisiti

Gli strumenti ABI utilizzano libabigail, una libreria e una raccolta di strumenti, per analizzare i binari. Un opportuno insieme di binari precompilati viene fornito con i kernel-build-tools e viene utilizzato automaticamente con build_abi.sh .

Per utilizzare le attrezzature di livello inferiore (come dump_abi ), aggiungere gli strumenti kernel-build-al PATH .

3. Costruisci il kernel e la sua rappresentazione ABI

A questo punto si è pronti a costruire un kernel con la toolchain corretta e per estrarre una rappresentazione ABI dai suoi binari ( vmlinux + moduli).

Simile al consueto processo di compilazione del kernel Android (utilizzando build.sh ), questo passaggio richiede l'esecuzione build_abi.sh .

BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh

Che costruisce il kernel ed estrae la rappresentazione ABI nel out_abi sottodirectory. In questo caso out/android12-5.10/dist/abi.xml è un link simbolico a out_abi/android12-5.10/dist/abi-<id>.xml . < id> è calcolata mediante l'esecuzione git describe contro l'albero dei sorgenti del kernel.

4. Analizzare le differenze ABI tra la build e una rappresentazione di riferimento

build_abi.sh analizza e segnala eventuali differenze ABI quando viene fornito un riferimento tramite la variabile di ambiente ABI_DEFINITION . ABI_DEFINITION deve puntare ad un file di riferimento rispetto alla sorgente del kernel, e può essere specificato sulla linea di comando o, più comunemente, come valore in build.config. Quanto segue fornisce un esempio:

BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh

Nel comando precedente, build.config.gki.aarch64 definisce il file di riferimento (come ABI_DEFINITION=android/abi_gki_aarch64.xml ), e diff_abi chiamate abidiff per confrontare la rappresentazione ABI appena generato contro il file di riferimento. build_abi.sh stampa la posizione del report ed emette una breve relazione per eventuali rotture ABI. Se vengono rilevate rotture, build_abi.sh termina e restituisce un codice diverso da zero.

5. Aggiorna la rappresentazione ABI (se richiesta)

Per aggiornare la rappresentazione ABI, invoke build_abi.sh con il --update bandiera. Si aggiorna il corrispondente abi.xml di file che è definito da build.config . Per stampare le differenze ABI causa l'aggiornamento, richiamare lo script con --print-report . Assicurati di includere il report nel messaggio di commit quando si aggiorna abi.xml file.

6. Lavorare con le liste di simboli

Parametrizzazione build_abi.sh con KMI liste dei simboli per simboli filtro durante l'estrazione ABI. Questi sono file di testo normale che elencano i simboli del kernel ABI rilevanti. Ad esempio, un file di elenco simbolo con il seguente contenuto limita l'analisi ABI ai simboli ELF con i nomi symbol1 e symbol2 :

[abi_symbol_list]
   symbol1
   symbol2

Le modifiche ad altri simboli ELF non sono considerate. Un file di elenco simbolo può essere specificato nel corrispondente build.config file di configurazione con KMI_SYMBOL_LIST= come file relativo alla directory dei sorgenti del kernel ( $KERNEL_DIR ). Per fornire un livello di organizzazione, è possibile specificare i file elenco dei simboli aggiuntivi utilizzando ADDITIONAL_KMI_SYMBOL_LISTS= nel build.config file. Questo specifica ulteriori file di elenco simbolo, relativi a $KERNEL_DIR ; separare più nomi di file per spazi bianchi.

Per creare una lista simbolo iniziale o per aggiornare uno esistente, è necessario utilizzare il build_abi.sh script con l' --update-symbol-list dei parametri.

Quando lo script viene eseguito con una configurazione appropriata, si costruisce il kernel ed estrae i simboli esportati da vmlinux moduli e GKI e che sono richiesti da qualsiasi altro modulo nell'albero.

Considerate vmlinux esportare i seguenti simboli (di solito fatto attraverso EXPORT_SYMBOL* macro):

  func1
  func2
  func3

Inoltre, immaginate c'erano due moduli vendor, modA.ko e modB.ko , che richiedono i seguenti simboli (in altre parole, essi elenco undefined voci di simboli nella loro tabella dei simboli):

 modA.ko:    func1 func2
 modB.ko:    func2

Dal punto di vista della stabilità ABI, func1 e func2 deve essere mantenuto stabile, come sono utilizzati da un modulo esterno. Al contrario, mentre func3 viene esportato, esso non viene utilizzato attivamente (in altre parole, non è necessario) da qualsiasi modulo. Così, l'elenco dei simboli contiene func1 e func2 solo.

Per creare o aggiornare un elenco simbolo esistente, build_abi.sh deve essere eseguito nel modo seguente:

BUILD_CONFIG=path/to/build.config.device build/build_abi.sh --update-symbol-list

In questo esempio, build.config.device deve includere diverse opzioni di configurazione:

  • vmlinux deve essere in FILES lista.
  • KMI_SYMBOL_LIST deve essere impostato e indicando la lista simbolo KMI di aggiornamento.
  • GKI_MODULES_LIST deve essere impostato e indicando la lista dei moduli GKI. Questo percorso è solitamente android/gki_aarch64_modules .

Lavorare con gli strumenti ABI di livello inferiore

Maggior parte degli utenti solo bisogno di usare build_abi.sh . In alcuni casi, potrebbe essere necessario lavorare direttamente con gli strumenti ABI di livello inferiore. I due comandi utilizzati da build_abi.sh , dump_abi e diff_abi , sono a disposizione per estrarre e confrontare i file ABI. Vedere le sezioni seguenti per i loro usi.

Creazione di rappresentazioni ABI da alberi del kernel

Fornito di un albero del kernel Linux con costruito vmlinux moduli e del kernel, lo strumento dump_abi crea una rappresentazione ABI utilizzando lo strumento ABI selezionato. Una chiamata di esempio ha il seguente aspetto:

dump_abi --linux-tree path/to/out --out-file /path/to/abi.xml

Il file abi.xml contiene una rappresentazione ABI testuale della combinata, osservabile ABI di vmlinux ed i moduli del kernel nella directory data. Questo file può essere utilizzato per l'ispezione manuale, ulteriori analisi o come file di riferimento per rafforzare la stabilità ABI.

Confronto tra rappresentazioni ABI

Rappresentazioni ABI creati da dump_abi possono essere confrontati con diff_abi . Utilizzare lo stesso abi-strumento sia per dump_abi e diff_abi . Una chiamata di esempio ha il seguente aspetto:

diff_abi --baseline abi1.xml --new abi2.xml --report report.out

Il report generato elenca le modifiche ABI rilevate che influiscono sul KMI. I file specificati come baseline e new sono rappresentazioni ABI che sono stati raccolti con dump_abi . diff_abi propaga il codice di uscita dello strumento sottostante e quindi restituisce un valore diverso da zero quando i ABI confrontati sono incompatibili.

Utilizzo degli elenchi di simboli KMI

Per rappresentazioni filtro creati con dump_abi simboli oa filtro rispetto ai diff_abi , utilizzare il parametro --kmi-symbol-list , che prende un percorso di un file KMI simbolo lista:

dump_abi --linux-tree path/to/out --out-file /path/to/abi.xml --kmi-symbol-list /path/to/symbol_list_file

Confronto dei binari del kernel con il riferimento GKI KMI

Mentre si sta lavorando sulla conformità GKI kernel, è utile confrontare regolarmente una build del kernel locale per un riferimento rappresentazione GKI KMI senza dover utilizzare build_abi.sh . Lo strumento gki_check è uno strumento leggero per fare esattamente questo. Dato un albero di compilazione del kernel Linux locale, una chiamata di esempio per confrontare la rappresentazione dei binari locali con, ad esempio, questo è come confrontare con la rappresentazione 5.4:

build/abi/gki_check --linux-tree path/to/out/ --kernel-version 5.4

gki_check utilizza nomi dei parametri coerenti con dump_abi e diff_abi . Quindi, --kmi-symbol-list path/to/kmi_symbol_list_file può essere utilizzato per limitare il confronto simboli consentiti passando lista segnali KMI.

Affrontare le rotture ABI

Ad esempio, la seguente patch introduce un'evidente rottura dell'ABI:

 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 */

Quando si esegue build_abi.sh di nuovo con questa patch applicata, le uscite utensili con un codice di errore diverso da zero e riporta una differenza ABI simile a questo:

 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:
  [...]

Riparare un ABI rotto su Android Gerrit

Se non hai violato intenzionalmente l'ABI del kernel, devi indagare, utilizzando le indicazioni fornite dagli strumenti di monitoraggio ABI. Le cause più comuni di rotture sono funzioni aggiunte o cancellate, strutture dati modificate o modifiche all'ABI causate dall'aggiunta di opzioni di configurazione che portano a una delle suddette. Inizia affrontando i problemi rilevati dallo strumento.

È possibile riprodurre il test di ABI localmente eseguendo il seguente comando con gli stessi argomenti che si sarebbe usato per l'esecuzione di build/build.sh :

Questo è un comando di esempio per i kernel GKI:

BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh

Aggiornamento del kernel ABI

Se è necessario aggiornare la rappresentazione kernel ABI, allora è necessario aggiornare il corrispondente abi.xml file dei sorgenti del kernel. Il modo più conveniente per farlo è quello di utilizzare build/build_abi.sh in questo modo:

build/build_abi.sh --update --print-report

Utilizzare gli stessi argomenti che si sarebbe usato per eseguire build/build.sh . Questo aggiorna il corretto abi.xml nell'albero dei sorgenti e le stampe delle differenze rilevate. In pratica, includi il report stampato (breve) nel messaggio di commit (almeno parzialmente).

Rami del kernel Android con ABI predefinito

Alcuni rami del kernel sono dotati di rappresentazioni ABI predefinite per Android come parte della loro distribuzione di origine. Queste rappresentazioni ABI sono destinati ad essere precisi, e per riflettere il risultato di build_abi.sh come se si eseguirà da soli. Come l'ABI è fortemente influenzato da varie opzioni di configurazione del kernel, questi .xml file di solito appartengono ad una determinata configurazione. Ad esempio, il common-android12-5.10 ramo contiene un abi_gki_aarch64.xml che corrisponde al risultato generazione quando utilizza il build.config.gki.aarch64 . In particolare, build.config.gki.aarch64 riferisce anche a questo file attraverso ABI_DEFINITION .

Tali rappresentazioni ABI predefiniti vengono utilizzati come definizione di base quando si confrontano con diff_abi . Ad esempio, per convalidare una patch del kernel per quanto riguarda eventuali modifiche alla ABI, creare la rappresentazione ABI con la patch applicata e utilizzare diff_abi per confrontarlo con l'ABI previsto per quel particolare albero di origine o di configurazione. Se ABI_DEFINITION è impostato, in esecuzione build_abi.sh di conseguenza farà.

Applicazione della KMI utilizzando il controllo delle versioni del modulo

La GKI kernel utilizzo del modulo delle versioni ( CONFIG_MODVERSIONS ) per far rispettare KMI in fase di esecuzione. Versioning modulo può causare errori di CRC di mismatch al modulo di carico-tempo se la KMI previsto di un modulo non corrisponde al vmlinux KMI. Ad esempio, ecco un errore tipico che si verifica al modulo di carico-tempo a causa di una mancata corrispondenza 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 ''

Usi del controllo delle versioni del modulo

Il versionamento del modulo è utile per molte ragioni:

  1. Rileva i cambiamenti nella visibilità della struttura dei dati. Se i moduli possono modificare strutture di dati opache, come strutture di dati che non fanno parte del KMI, i moduli si interromperanno dopo modifiche future alla struttura.
  2. Aggiunge un controllo in fase di esecuzione per evitare di caricare accidentalmente un modulo che non è compatibile con KMI con il kernel. (Come quando un modulo corrente viene caricato in una data successiva da un nuovo kernel che è incompatibile.) Questo è preferibile ad avere successivi problemi di runtime o crash del kernel difficili da eseguire.
  3. abidiff ha limitazioni nell'identificare differenze ABI in alcuni casi contorti che CONFIG_MODVERSIONS possono catturare.

Come esempio di (1), si consideri la fwnode campo struct device . Tale campo devono essere opaco ai moduli in modo che essi non possono apportare modifiche ai campi di device->fw_node o ipotesi make sulla sua dimensione.

Tuttavia, se un modulo include <linux/fwnode.h> (direttamente o indirettamente), allora il fwnode campo nel struct device smette di essere opaca ad esso. Il modulo può quindi apportare modifiche alle device->fwnode->dev o device->fwnode->ops . Questo è problematico per diversi motivi:

  1. Può rompere le ipotesi che il codice del kernel principale sta facendo sulle sue strutture di dati interne.

  2. Se un aggiornamento del kernel futuro cambia il struct fwnode_handle (il tipo di dati di fwnode ), allora il modulo non funziona con il nuovo kernel. Inoltre, abidiff non mostreranno differenze perché il modulo sta rompendo il KMI manipolando direttamente strutture interne di dati in modi che non possono essere catturati soltanto controllando la rappresentazione binaria.

L'abilitazione del controllo delle versioni dei moduli previene tutti questi problemi.

Verifica delle discrepanze CRC senza avviare il dispositivo

Qualsiasi compilazione del kernel con CONFIG_MODVERSIONS abilitato non genera un Module.symvers file come parte del processo di generazione. Il file ha una riga per ogni simbolo esportato dal vmlinux ei moduli. Ogni linea è costituito dal valore CRC, nome del simbolo, il simbolo dello spazio dei nomi, vmlinux o il nome del modulo che sta esportando il simbolo, e il tipo di esportazione (ad esempio, EXPORT_SYMBOL vs. EXPORT_SYMBOL_GPL ).

È possibile confrontare i Module.symvers file tra la build GKI e la vostra build per verificare la presenza di eventuali differenze CRC nei simboli esportati da vmlinux . Se c'è una differenza di valore CRC in qualsiasi simbolo esportati da vmlinux ed è utilizzato da uno dei moduli caricati nel dispositivo, il modulo non verrà caricato.

Se non si dispone di tutti gli artefatti costruire, ma basta avere le vmlinux file del kernel GKI e il kernel, è possibile confrontare i valori CRC per un simbolo specifico eseguendo il comando seguente su entrambi i kernel, quindi confrontando l'output:

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

Ad esempio, per controllare il valore CRC per il module_layout simbolo,

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

Risolvere la mancata corrispondenza del CRC

Se si verifica una mancata corrispondenza CRC durante il caricamento del modulo, ecco come risolverlo:

  1. Costruire il kernel GKI e il kernel del dispositivo, e aggiungere KBUILD_SYMTYPES=1 davanti al comando che si utilizza per compilare il kernel. Nota, quando si utilizza build_abi.sh, questo è implicitamente impostato già. Questo genererà un .symtypes file per ogni .o file. Per esempio:

    KBUILD_SYMTYPES=1 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
    
  2. Trova il .c file in cui viene esportato il simbolo con CRC non corrispondente. Per esempio:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
    
  3. Che .c file ha un corrispondente .symtypes file nel GKI, e il dispositivo manufatti di compilazione del kernel.

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

    un. Il formato di questo file è una riga (potenzialmente molto lunga) per simbolo.

    B. [s|u|e|etc]# all'inizio della riga indica il simbolo è di tipo di dati [struct|union|enum|etc] . Ad esempio, t#bool typedef _Bool bool .

    C. Un manca # prefisso all'inizio della riga indica il simbolo è una funzione. Per esempio,
    find_module s#module * find_module ( const char * ) .

  4. Confronta questi due file e correggi tutte le differenze.

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

Se un kernel mantiene un simbolo o tipo di dati opaco ai moduli e l'altro kernel non, quindi si presenta come una differenza tra i .symtypes file dei due kernel. Il .symtypes file da uno dei noccioli ha UNKNOWN per un simbolo e il .symtypes file da un altro kernel ha una vista espansa del tipo di simbolo o di dati.

Ad esempio, si supponga di aggiungere questa linea al include/linux/device.h nel kernel:

 #include <linux/fwnode.h>

Che provoca disallineamenti CRC, con uno di loro per module_layout() . Se si confrontano i module.symtypes per quel simbolo, sembra che questo:

 $ 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 proprio kernel ha come UNKNOWN e il kernel GKI ha la vista espansa del simbolo (molto improbabile), quindi unire l'ultimo Android Comune Kernel nel kernel in modo che si sta utilizzando l'ultima base di kernel GKI.

Quasi sempre, il kernel GKI ha come UNKNOWN , ma il vostro kernel ha i dettagli interni del simbolo a causa delle modifiche apportate al kernel. Questo perché uno dei file nel vostro kernel aggiunto un #include che non è presente nel kernel GKI.

Per identificare il #include che causa la differenza, attenersi alla seguente procedura:

  1. Aprire il file di intestazione che definisce il simbolo o il tipo di dati con questa differenza. Ad esempio, modificare include/linux/fwnode.h per il struct fwnode_handle .
  2. Aggiungi il seguente codice nella parte superiore del file di intestazione:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. Poi nel modulo .c del file (quella che ha una mancata corrispondenza CRC), aggiungere la seguente come prima riga prima di qualsiasi delle #include linee.

    #define CRC_CATCH 1
    
  4. Ora compila il tuo modulo. Si otterrà un errore di generazione-time che mostra la catena di file di intestazione #include che ha portato a questa mancata corrispondenza CRC. Per 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"
    
  5. Uno dei link in questa catena di #include è causa di un cambiamento fatto nel kernel, che manca nel kernel GKI.

  6. Una volta identificato il cambiamento, tornare nel vostro kernel o caricarlo su ACK e ottenere si è fusa .

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. Tipicamente, abidiff catture questo, ma se manca qualsiasi causa di carenze di rilevamento noti, il MODVERSIONS meccanismo può catturarli.

Ad esempio, supponiamo di apportare la seguente modifica nel kernel:

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

Che potrebbero causare un sacco di disallineamenti CRC (come molti simboli sono indirettamente interessati da questo tipo di cambiamento) e uno di loro sarebbe per devm_of_platform_populate() .

Se si confrontano i .symtypes file per quel simbolo, potrebbe assomigliare a questo:

 $ 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, attenersi alla seguente procedura:

  1. Trova la definizione del simbolo nel codice sorgente (di solito in .h file).
  2. Se c'è una differenza simbolo evidente tra il kernel e il kernel GKI, fare una git blame per trovare il commit.
  3. A volte un simbolo viene eliminato in un albero e si desidera eliminarlo nell'altro albero. Per trovare la modifica che ha eliminato la riga, eseguire questo comando nell'albero in cui è stata eliminata la riga:

    un. git log -S "copy paste of deleted line/word" -- <file where it was deleted>

    B. Otterrai un elenco abbreviato di commit. Il primo è probabilmente quello che stai cercando. In caso contrario, scorrere l'elenco fino a trovare il commit.

  4. Una volta identificato il cambiamento, o riportare nel vostro kernel o caricarlo su ACK e ottenere si è fusa .