Surveillance des ABI du kernel Android

Vous pouvez utiliser les outils de surveillance de l'interface binaire d'application (ABI) disponibles dans Android 11 ou version ultérieure, pour stabiliser le noyau ABI des noyaux Android. L'outil collecte et compare les représentations ABI des binaires de noyau existants (vmlinux + modules GKI). Ces représentations ABI sont les fichiers .stg et les listes de symboles. L'interface sur laquelle la représentation donne une vue s'appelle l'interface de module de kernel (KMI). Vous pouvez utiliser ces outils pour suivre et atténuer les modifications apportées au KMI.

Les outils de surveillance de l'ABI développé dans AOSP et utilise STG (ou libabigail po Android 13 ou version antérieure) pour générer et comparer représentations.

Cette page décrit les outils, le processus de collecte et d'analyse des représentations ABI, ainsi que l'utilisation de ces représentations pour assurer la stabilité de l'ABI dans le noyau. Cette page fournit également des informations sur la contribution des modifications vers les noyaux Android.

Procédure

L'analyse de l'ABI du noyau nécessite plusieurs étapes, dont la plupart peuvent être automatisées :

  1. Compilez le kernel et sa représentation ABI.
  2. Analysez les différences d'ABI entre la compilation et une référence.
  3. Mettez à jour la représentation de l'ABI (si nécessaire).
  4. Utiliser des listes de symboles

Les instructions suivantes s'appliquent à tout noyau que vous pouvez compiler à l'aide d'une chaîne d'outils compatible (telle que la chaîne d'outils Clang précompilée). repo manifests sont disponibles pour toutes les branches courantes du noyau Android et pour plusieurs noyaux spécifiques à l'appareil, ils garantissent l'utilisation de la chaîne d'outils appropriée créer une distribution de noyau pour l'analyse.

Listes de symboles

Le KMI n'inclut pas tous les symboles du noyau,ni même tous les plus de 30 000 et les symboles exportés. À la place, les symboles pouvant être utilisés par les modules du fournisseur sont listés explicitement dans un ensemble de fichiers de liste de symboles gérés publiquement à la racine de l'arborescence du noyau. L'union de tous les symboles de tous les fichiers de liste de symboles définit l'ensemble des symboles KMI maintenus comme stables. Un exemple de fichier de liste de symboles est abi_gki_aarch64_db845c, qui déclare les symboles requis pour la DragonBoard 845c.

Seuls les symboles listés dans une liste de symboles, ainsi que leurs structures et définitions associées, sont considérés comme faisant partie du KMI. Vous pouvez publier des modifications dans vos listes de symboles si les symboles dont vous avez besoin ne sont pas présents. Après le déploiement des nouvelles interfaces, une liste de symboles et qu'ils font partie de la description du KMI, ils sont conservés comme stables et ne doit pas être supprimé de la liste de symboles ni modifié une fois la branche est figée.

Chaque branche du noyau KMI d'Android Common Kernel (ACK) possède son propre ensemble de symboles . Aucune tentative visant à assurer la stabilité de l'ABI entre différents noyau KMI n'est effectuée branches. Par exemple, le KMI pour android12-5.10 est complètement indépendant du KMI pour android13-5.10.

Les outils ABI utilisent des listes de symboles KMI pour limiter les interfaces à surveiller pour la stabilité. La liste principale des symboles contient les symboles requis par les modules de noyau GKI. Les fournisseurs doivent envoyer et mettre à jour des listes de symboles supplémentaires pour s'assurer que les interfaces sur lesquelles ils s'appuient conservent la compatibilité ABI. Par exemple, pour afficher une liste de listes de symboles pour android13-5.15, consultez https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android.

Une liste de symboles contient les symboles qui sont signalés comme nécessaires pour le du fournisseur ou de l'appareil. La liste complète utilisée par les outils est l'union de tous les fichiers de liste de symboles KMI. Les outils ABI déterminent les détails de chaque symbole, y compris la signature de la fonction et les structures de données imbriquées.

Lorsque le KMI est figé, aucune modification n'est autorisée aux interfaces KMI existantes. ils sont stables. Toutefois, les fournisseurs sont libres d'ajouter des symboles au KMI à tout moment. tant que les ajouts n'affectent pas la stabilité de l'ABI existante. Les symboles nouvellement ajoutés sont considérés comme stables dès qu'ils sont cités dans une liste de symboles KMI. Les symboles ne doivent pas être supprimés d'une liste pour un noyau, sauf s'ils peuvent être confirmés qu’aucun appareil n’a jamais été livré avec une dépendance sur ce symbole.

Vous pouvez générer une liste de symboles KMI pour un appareil en suivant les instructions de Utiliser les listes de symboles De nombreux partenaires soumettent une liste de symboles par ACK, mais ce n'est pas une exigence stricte. Si cela vous aide à la maintenance, vous pouvez envoyer plusieurs listes de symboles.

Étendez votre KMI

Alors que les symboles KMI et les structures associées sont conservés comme stables (ce qui signifie les modifications qui rompent les interfaces stables dans un noyau avec un KMI figé ne peuvent pas être le noyau GKI reste ouvert aux extensions pour que les appareils plus tard dans l'année n'ont pas besoin de définir toutes leurs dépendances avant que le KMI ne soit est figée. Pour étendre le KMI, vous pouvez ajouter de nouveaux symboles au KMI pour les nouvelles ou les fonctions de kernel exportées existantes, même si le KMI est gelé. Nouveau noyau des correctifs peuvent également être acceptés s'ils n'entravent pas le KMI.

À propos des erreurs KMI

Un noyau dispose de sources, et les binaires sont créés à partir de ces sources. Les branches du kernel surveillées par l'ABI incluent une représentation ABI de l'ABI GKI actuelle (sous la forme d'un fichier .stg). Après les binaires (vmlinux, Image et des modules GKI) sont compilés, une représentation d'ABI peut être extraite binaires. Toute modification apportée à un fichier source du kernel peut affecter les binaires, et par conséquent également l'.stg extrait. L'analyseur AbiAnalyzer compare les validé le fichier .stg avec celui extrait des artefacts de compilation et définit un Étiquette lint-1 sur le changement de Gerrit en cas de différence sémantique.

Gérer les erreurs ABI

Par exemple, le correctif suivant introduit une faille évidente dans l'ABI:

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 42786e6364ef..e15f1d0f137b 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -657,6 +657,7 @@ struct mm_struct {
                ANDROID_KABI_RESERVE(1);
        } __randomize_layout;

+       int tickle_count;
        /*
         * The mm_cpumask needs to be at the end of mm_struct, because it
         * is dynamically sized based on nr_cpu_ids.

Lorsque vous exécutez l'ABI de compilation avec ce correctif appliqué, l'outil s'arrête avec un code d'erreur différent de zéro et signale une différence d'ABI semblable à celle-ci :

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

Différences d'ABI détectées au moment de la compilation

La cause la plus courante des erreurs est qu'un pilote utilise un nouveau symbole du noyau qui ne figure dans aucune des listes de symboles.

Si le symbole n'est pas inclus dans la liste des symboles (android/abi_gki_aarch64), vous devez d'abord vérifier qu'il est exporté avec EXPORT_SYMBOL_GPL(symbol_name), puis mettre à jour la représentation XML de l'ABI et la liste des symboles. Par exemple, les modifications suivantes ajoutent la nouvelle fonctionnalité de SF incrémentielle dans la branche android-12-5.10, qui inclut la mise à jour de la liste de symboles et de la représentation XML de l'ABI.

  • L'exemple de modification de caractéristique est disponible aosp/1345659.
  • L'exemple de liste de symboles se trouve dans (aosp/1346742).
  • L'exemple de modification XML de l'ABI est aosp/1349377.

Si le symbole a été exporté (par vous ou précédemment), mais qu'il n'a autre pilote l'utilise, vous pouvez obtenir une erreur de compilation semblable à la suivante.

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

Pour résoudre le problème, mettez à jour la liste des symboles KMI dans le noyau et dans l'ACK (voir Mettre à jour la représentation de l'ABI. Pour obtenir un exemple de mise à jour de la liste des symboles et du fichier XML ABI dans l'ACK, consultez aosp/1367601.

Résoudre les erreurs ABI du noyau

Vous pouvez gérer les erreurs de l'ABI du kernel en refactorant le code pour ne pas modifier l'ABI ou en mettant à jour la représentation de l'ABI. Utilisez le tableau suivant pour déterminer la meilleure approche dans votre cas.

Organigramme de la rupture de l'ABI

Figure 1 : Résolution des erreurs ABI

Refactoriser le code pour éviter les modifications de l'ABI

Faites tout votre possible pour éviter de modifier l'ABI existant. Dans de nombreux cas, vous pouvez refactoriser votre code pour supprimer les modifications qui affectent l'ABI ;

  • Refactorisation des modifications du champ struct. Si une modification modifie l'ABI pour un débogage ajoutez un #ifdef autour des champs (dans les structs et les ) et assurez-vous que le CONFIG utilisé pour #ifdef est désactivé pour defconfig de production et gki_defconfig. Pour savoir comment ajouter une configuration de débogage à une struct sans endommager l'ABI, consultez ce correctif.

  • Fonctionnalités de refactorisation pour ne pas modifier le noyau principal. Si de nouvelles fonctionnalités ont besoin à ajouter à l'ACK afin de prendre en charge les modules partenaires, essayez de refactoriser l'ABI pour éviter de modifier l'ABI du noyau. Pour voir un exemple d'utilisation l'ABI du noyau existante pour ajouter des fonctionnalités sans modifier les ABI du noyau se réfèrent aosp/1312213.

Corriger une ABI défectueuse sur Android Gerrit

Si vous n'avez pas intentionnellement endommagé l'ABI du kernel, vous devez procéder à une analyse en vous appuyant sur les conseils fournis par les outils de surveillance de l'ABI. Les causes les plus courantes de cassures sont les modifications des structures de données et les modifications du CRC du symbole associé, ou les modifications des options de configuration qui entraînent l'une des causes mentionnées ci-dessus. Commencez par résoudre les problèmes détectés par l'outil.

Vous pouvez reproduire les résultats de l'ABI localement. Pour ce faire, consultez la section Compiler le kernel et sa représentation ABI.

À propos des étiquettes lint-1

Si vous importez des modifications dans une branche contenant un KMI figé ou finalisé, les modifications doivent passer l'AbiAnalyzer pour s'assurer qu'elles n'affectent pas l'ABI stable de manière incompatible. Au cours de ce processus, AbiAnalyzer recherche le rapport ABI créé lors de la compilation (une compilation étendue qui effectue la compilation normale, puis certaines étapes d'extraction et de comparaison ABI.

Si AbiAnalyzer trouve un rapport non vide, il définit le libellé lint-1 et l'envoi de la modification est bloqué jusqu'à ce qu'il soit résolu ; jusqu'à ce que le patchset ne reçoive Libellé lint+1.

Mettre à jour l'ABI du noyau

Si la modification de l'ABI est inévitable, vous devez appliquer vos modifications de code, la représentation de l'ABI et la liste des symboles à l'ACK. Pour que lint supprimez -1 sans affecter la compatibilité GKI, procédez comme suit:

  1. Importez les modifications de code dans l'ACK.

  2. Attendez de recevoir un code-review +2 pour le lot de correctifs.

  3. Mettez à jour la représentation de l'ABI de référence.

  4. Fusionnez vos modifications de code avec celles de la mise à jour de l'ABI.

Importer les modifications du code d'ABI dans l'ACK

La mise à jour de l'ABI ACK dépend du type de modification apportée.

  • Si une modification de l'ABI est liée à une fonctionnalité qui affecte les tests CTS ou VTS, changement peut généralement être sélectionné cerise sur ACK tel quel. Par exemple:

  • Si une modification de l'ABI concerne une fonctionnalité pouvant être partagée avec l'ACK, cette modification peut être sélectionnée cerise sur ACK en l’état. Par exemple, les modifications ne sont pas nécessaires pour le test CTS ou VTS, mais peuvent être partagés avec ACK:

    • aosp/1250412 est un changement de fonctionnalité thermique.
    • (aosp/1288857). correspond à un changement de EXPORT_SYMBOL_GPL.
  • Si un changement d'ABI introduit une nouvelle fonctionnalité qui n'a pas besoin d'être incluse dans l’ACK, vous pouvez introduire les symboles dans ACK à l’aide d’un bouchon comme décrit dans dans la section suivante.

Utiliser des bouchons pour l'acquittement

Les bouchons ne doivent être nécessaires que pour les modifications de kernel de base qui ne profitent pas à l'ACK, telles que les modifications de performances et d'alimentation. La liste suivante fournit des exemples détaillés de bouchons et de sélections partielles dans l'ACK pour GKI.

  • Bouchon de fonctionnalité de l'isolation du noyau (aosp/1284493). Les capacités dans ACK ne sont pas nécessaires, mais les symboles doivent être présents dans ACK pour que vos modules utilisent ces symboles.

  • Symbole d'espace réservé pour le module du fournisseur (aosp/1288860).

  • Sélection ABI de la fonctionnalité de suivi des événements mm par processus (aosp/1288454). Le correctif d'origine a été sélectionné pour ACK, puis coupé pour n'inclure que les modifications nécessaires pour résoudre les différences d'ABI pour task_struct et mm_event_count Ce correctif met également à jour l'énumération mm_event_type pour qu'elle contienne les derniers membres.

  • Sélection partielle des modifications de l'ABI de la structure thermique qui nécessitaient plus que de simples en ajoutant les nouveaux champs d'ABI.

    • Corriger (aosp/1255544). Résolution des différences d'ABI entre le noyau partenaire et l'ACK

    • Corriger (aosp/1291018). Correction des problèmes fonctionnels détectés lors des tests GKI du correctif précédent. La correction consistait à initialiser la structure de paramètres du capteur pour enregistrer plusieurs zones thermiques sur un seul capteur.

  • Modifications de l'ABI CONFIG_NL80211_TESTMODE (aosp/1344321). Ce correctif a ajouté les modifications de structure nécessaires pour l'ABI et a permis de s'assurer d'autres champs n'entraînaient aucune différence fonctionnelle, permettant ainsi aux partenaires d'inclure CONFIG_NL80211_TESTMODE dans leurs noyaux de production tout en continuant à maintenir la conformité GKI.

Appliquer le KMI au moment de l'exécution

Les noyaux GKI utilisent les options de configuration TRIM_UNUSED_KSYMS=y et UNUSED_KSYMS_WHITELIST=<union of all symbol lists>, qui limitent les symboles exportés (tels que les symboles exportés à l'aide de EXPORT_SYMBOL_GPL()) à ceux figurant sur une liste de symboles. Tous les autres symboles ne sont pas exportés, et le chargement d'un module nécessitant un symbole non exporté est refusé. Cette restriction est appliquée au moment de la compilation, et les entrées manquantes sont signalées.

À des fins de développement, vous pouvez utiliser une version de noyau GKI qui n'inclut pas le découpage des symboles (tous les symboles généralement exportés peuvent alors être utilisés) ; Pour localiser ces builds, recherchez les builds kernel_debug_aarch64 sur ci.android.com

Appliquer le KMI à l'aide de la gestion des versions des modules

Les noyaux GKI (Generic Kernel Image) utilisent la gestion des versions de module (CONFIG_MODVERSIONS) comme mesure supplémentaire pour veiller à la conformité avec le KMI de l'environnement d'exécution. La gestion des versions de module peut entraîner une incohérence au niveau du contrôle de redondance cyclique (CRC) au moment du chargement d'un module, si son KMI attendu ne correspond pas vmlinux KMI. Par exemple, voici une erreur courante qui se produit au moment du chargement du module en raison d'une non-concordance de CRC pour le symbole 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 ''

Utilisations de la gestion des versions des modules

La gestion des versions de module est utile pour les raisons suivantes:

  • La gestion des versions des modules permet de détecter les modifications de la visibilité de la structure des données. Si les modules modifier des structures de données opaques, c'est-à-dire des structures de données qui ne font pas partie KMI, ils ne fonctionnent pas après des modifications futures de la structure.

    Prenons l'exemple du champ fwnode dans struct device. Ce champ DOIT être opaque pour les modules afin qu'ils ne puissent pas modifier les champs de device->fw_node ni faire d'hypothèses sur sa taille.

    Toutefois, si un module inclut <linux/fwnode.h> (directement ou indirectement), alors le champ fwnode dans struct device n'est plus opaque. La module peut ensuite modifier device->fwnode->dev ou device->fwnode->ops Ce scénario est problématique pour plusieurs raisons, comme suit:

    • Il peut briser les hypothèses que le code du noyau principal fait sur ses structures de données internes.

    • Si une mise à jour ultérieure du noyau modifie le struct fwnode_handle (les données type de fwnode), cela signifie que le module ne fonctionne plus avec le nouveau noyau. De plus, stgdiff n'affichera aucune différence, car le module ne fonctionnera pas le KMI en manipulant directement les structures de données internes de manière impossible être capturé en inspectant uniquement la représentation binaire.

  • Un module actuel est considéré comme incompatible avec KMI lorsqu'il est chargé à une date ultérieure par un nouveau noyau incompatible. La gestion des versions de module ajoute une vérification de l'exécution éviter de charger accidentellement un module qui n’est pas compatible KMI avec le noyau. Cette vérification évite les problèmes d'exécution difficiles à déboguer et les plantages du noyau pouvant résulter d'une incompatibilité non détectée dans le KMI.

L'activation de la gestion des versions des modules évite tous ces problèmes.

Vérifier les incohérences de CRC sans démarrer l'appareil

stgdiff compare et signale les différences de CRC entre les noyaux, ainsi que d'autres différences ABI.

De plus, une compilation complète du noyau avec CONFIG_MODVERSIONS activé génère Module.symvers dans le cadre du processus de compilation normal. Ce fichier comporte une ligne pour chaque symbole exporté par le noyau (vmlinux) et les modules. Chaque ligne comprend la valeur CRC, le nom du symbole, l'espace de noms du symbole, le nom vmlinux ou le nom du module qui exporte le symbole, ainsi que le type d'exportation (par exemple, EXPORT_SYMBOL par rapport à EXPORT_SYMBOL_GPL).

Vous pouvez comparer les fichiers Module.symvers entre le build GKI et votre build. pour vérifier les différences du CRC dans les symboles exportés par vmlinux. S'il y a est une différence de valeur CRC pour tout symbole exporté par vmlinux et qui est utilisé par l'un des modules que vous chargez sur votre appareil, le module ne charge.

Si vous ne disposez pas de tous les artefacts de compilation, mais que vous disposez des fichiers vmlinux du kernel GKI et de votre kernel, vous pouvez comparer les valeurs CRC d'un symbole spécifique en exécutant la commande suivante sur les deux kernels et en comparant la sortie :

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

Par exemple, la commande suivante vérifie la valeur CRC pour module_layout symbole:

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

Résoudre les problèmes de correspondance du CRC

Pour résoudre un problème de non-concordance de CRC lors du chargement d'un module, procédez comme suit :

  1. Créez le kernel GKI et le kernel de votre appareil à l'aide de l'option --kbuild_symtypes, comme indiqué dans la commande suivante :

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

    Cette commande génère un fichier .symtypes pour chaque fichier .o. Pour en savoir plus, consultez KBUILD_SYMTYPES dans Kleaf.

    Pour Android 13 et versions antérieures, créez le noyau GKI et le noyau de votre appareil en ajoutant KBUILD_SYMTYPES=1 au début de la commande utiliser pour créer le noyau, comme indiqué dans la commande suivante:

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

    Lorsque vous utilisez build_abi.sh,, l'indicateur KBUILD_SYMTYPES=1 est déjà défini implicitement.

  2. Recherchez le fichier .c dans lequel le symbole avec non-concordance CRC est exporté à l'aide de la commande suivante:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
  3. Le fichier .c possède un fichier .symtypes correspondant dans le GKI et les artefacts de compilation du kernel de votre appareil. Recherchez le fichier .c à l'aide des commandes suivantes :

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

    Voici les caractéristiques du fichier .c:

    • Le format du fichier .c est une ligne (potentiellement très longue) par symbole.

    • [s|u|e|etc]# au début de la ligne signifie que le symbole est de type de données [struct|union|enum|etc]. Exemple :

      t#bool typedef _Bool bool
      
    • S'il manque un préfixe # au début de la ligne, cela signifie que le symbole est une fonction. Exemple :

      find_module s#module * find_module ( const char * )
      
  4. Comparez les deux fichiers et corrigez toutes les différences.

Cas 1: différences dues à la visibilité du type de données

Si un noyau maintient un symbole ou un type de données opaque pour les modules et que l'autre ne le fait pas, cette différence apparaît entre les fichiers .symtypes des deux noyaux. Le fichier .symtypes de l'un des noyaux contient UNKNOWN pour un symbole, et le fichier .symtypes de l'autre noyau affiche une vue agrandie du symbole ou du type de données.

Par exemple, si vous ajoutez la ligne suivante au include/linux/device.h du noyau provoque des incohérences CRC, dont l'une pour module_layout():

 #include <linux/fwnode.h>

En comparant les module.symtypes de ce symbole, les différences suivantes apparaissent :

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

Si votre kernel a la valeur UNKNOWN et que le kernel GKI affiche la vue agrandie du symbole (très peu probable), fusionnez le dernier kernel Android Common dans votre kernel afin d'utiliser la dernière base de kernel GKI.

Dans la plupart des cas, le noyau GKI a une valeur de UNKNOWN, mais votre noyau contient les détails internes du symbole en raison des modifications apportées à votre noyau. C'est car l'un des fichiers de votre noyau a ajouté un #include qui n'est pas présent dans le noyau GKI.

Souvent, la solution consiste simplement à masquer le nouveau #include pour genksyms.

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

Sinon, pour identifier l'élément #include à l'origine de la différence, procédez comme suit : étapes:

  1. Ouvrez le fichier d'en-tête qui définit le symbole ou le type de données présentant cette différence. Par exemple, modifiez include/linux/fwnode.h pour struct fwnode_handle

  2. Ajoutez le code suivant en haut du fichier d'en-tête :

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. Dans le fichier .c du module qui présente une incohérence CRC, ajoutez le qui suit comme première ligne avant l'une des lignes #include.

    #define CRC_CATCH 1
    
  4. Compilez votre module. L'erreur qui en résulte au moment de la compilation montre la chaîne fichier d'en-tête #include à l'origine de cette incohérence dans le CRC. Exemple :

    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"
    

    L'un des maillons de cette chaîne de #include est dû à une modification apportée à votre noyau, qui est manquante dans le noyau GKI.

  5. Identifiez la modification, annulez-la dans votre kernel ou importez-la dans ACK et fusionnez-la.

Cas 2 : Différences dues à des modifications de type de données

Si la non-concordance du CRC pour un symbole ou un type de données n'est pas due à une différence en raison de modifications réelles (ajouts, suppressions ou modifications) le type de données lui-même.

Par exemple, la modification suivante dans votre noyau entraîne plusieurs erreurs CRC car de nombreux symboles sont indirectement affectés par ce type de modification:

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 problème de non-correspondance du CRC concerne devm_of_platform_populate().

Si vous comparez les fichiers .symtypes de ce symbole, ils peuvent se présenter comme suit :

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

Pour identifier le type modifié, procédez comme suit:

  1. Recherchez la définition du symbole dans le code source (généralement dans les fichiers .h).

    • Pour trouver les différences de symboles entre votre kernel et le kernel GKI, exécutez la commande suivante :
    git blame
    • Pour les symboles supprimés (lorsqu'un symbole est supprimé de l'arborescence et que vous la supprimer dans l'autre arborescence), vous devez trouver la modification a supprimé la ligne. Exécutez la commande suivante dans l'arborescence où la ligne a été supprimé:
    git log -S "copy paste of deleted line/word" -- <file where it was deleted>
  2. Passez en revue la liste des commits renvoyés pour trouver la modification ou la suppression. La le premier commit est probablement celui que vous recherchez. Si ce n'est pas le cas, allez dans la liste jusqu'à ce que vous trouviez le commit.

  3. Après avoir identifié la modification, annulez-la dans votre noyau ou l'importer sur l'ACK et l'obtenir fusionnés.