Surveillance ABI du noyau Android

Vous pouvez utiliser les outils de surveillance de l'interface binaire (ABI), disponibles dans Android 11 et versions ultérieures, pour stabiliser l'ABI intégré aux noyaux Android. L'outil collecte et compare les représentations ABI à partir des binaires du noyau existants (modules vmlinux + GKI). Ces représentations ABI sont les fichiers .stg et les listes de symboles. L'interface sur laquelle la représentation donne une vue est appelée Kernel Module Interface (KMI). Vous pouvez utiliser les outils pour suivre et atténuer les modifications apportées au KMI.

L'outil de surveillance ABI est développé en AOSP et utilise STG (ou libabigail dans Android 13 et versions antérieures) pour générer et comparer des 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 interne au noyau. Cette page fournit également des informations pour apporter des modifications aux noyaux Android.

Processus

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

  1. Construisez le noyau et sa représentation ABI .
  2. Analysez les différences ABI entre la build et une référence .
  3. Mettez à jour la représentation ABI (si nécessaire) .
  4. Travailler avec des listes de symboles .

Les instructions suivantes fonctionnent pour n'importe quel noyau que vous pouvez créer à l'aide d'une chaîne d'outils prise en charge (telle que la chaîne d'outils Clang prédéfinie). repo manifests sont disponibles pour toutes les branches communes du noyau Android et pour plusieurs noyaux spécifiques à un périphérique, ils garantissent que la chaîne d'outils appropriée est utilisée lorsque vous créez une distribution de noyau à des fins d'analyse.

Listes de symboles

Le KMI n'inclut pas tous les symboles du noyau ni même la totalité des plus de 30 000 symboles exportés. Au lieu de cela, les symboles qui peuvent être utilisés par les modules du fournisseur sont explicitement répertoriés dans un ensemble de fichiers de liste de symboles maintenus publiquement à la racine de l'arborescence du noyau. L'union de tous les symboles dans tous les fichiers de liste de symboles définit l'ensemble des symboles KMI maintenu comme stable. Un exemple de fichier de liste de symboles est abi_gki_aarch64_db845c , qui déclare les symboles requis pour le DragonBoard 845c .

Seuls les symboles répertoriés dans une liste de symboles et 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. Une fois que les nouvelles interfaces sont dans une liste de symboles et font partie de la description du KMI, elles sont maintenues comme stables et ne doivent pas être supprimées de la liste de symboles ou modifiées après le gel de la branche.

Chaque branche du noyau KMI Android Common Kernel (ACK) possède son propre ensemble de listes de symboles. Aucune tentative n'est faite pour assurer la stabilité ABI entre les différentes branches du noyau KMI. 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 dont la stabilité doit être surveillée. La liste principale des symboles contient les symboles requis par les modules du noyau GKI. Les fournisseurs doivent soumettre et mettre à jour des listes de symboles supplémentaires pour garantir que les interfaces sur lesquelles ils s'appuient maintiennent la compatibilité ABI. Par exemple, pour voir une liste de listes de symboles pour android13-5.15 , reportez-vous à https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android

Une liste de symboles contient les symboles signalés comme étant nécessaires pour un fournisseur ou un appareil particulier. 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 fonction et les structures de données imbriquées.

Lorsque le KMI est gelé, aucune modification n'est autorisée sur les interfaces KMI existantes ; ils sont stables. Cependant, les fournisseurs sont libres d'ajouter des symboles au KMI à tout moment, à condition que les ajouts n'affectent pas la stabilité de l'ABI existant. Les symboles nouvellement ajoutés sont maintenus aussi stables dès qu'ils sont cités par une liste de symboles KMI. Les symboles ne doivent pas être supprimés d'une liste pour un noyau à moins qu'il puisse être confirmé qu'aucun périphérique 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 Comment 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 facilite la maintenance, vous pouvez soumettre plusieurs listes de symboles.

Étendre le KMI

Bien que les symboles KMI et les structures associées soient maintenus stables (ce qui signifie que les modifications qui brisent les interfaces stables dans un noyau avec un KMI gelé ne peuvent pas être acceptées), le noyau GKI reste ouvert aux extensions afin que les appareils livrés plus tard dans l'année n'aient pas besoin de tout définir. leurs dépendances avant que le KMI ne soit gelé. Pour étendre le KMI, vous pouvez ajouter de nouveaux symboles au KMI pour les fonctions du noyau exportées nouvelles ou existantes, même si le KMI est gelé. Les nouveaux correctifs du noyau peuvent également être acceptés s'ils ne cassent pas le KMI.

À propos des casses KMI

Un noyau a des sources et les binaires sont construits à partir de ces sources. Les branches du noyau surveillées par ABI incluent une représentation ABI de l'ABI GKI actuel (sous la forme d'un fichier .stg ). Une fois les binaires ( vmlinux , Image et tous les modules GKI) construits, une représentation ABI peut être extraite des binaires. Toute modification apportée à un fichier source du noyau peut affecter les binaires et, par conséquent, également affecter le .stg extrait. L'analyseur AbiAnalyzer compare le fichier .stg validé avec celui extrait des artefacts de construction et définit une étiquette Lint-1 sur le changement dans Gerrit s'il trouve une différence sémantique.

Gérer les casses ABI

A titre d'exemple, le patch suivant introduit une rupture ABI très évidente :

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 build ABI avec ce correctif appliqué, les outils se terminent avec un code d'erreur différent de zéro et signalent une différence ABI similaire à 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 ABI détectées au moment de la construction

La raison la plus courante des erreurs est lorsqu'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 ABI et la liste des symboles. Par exemple, les modifications suivantes ajoutent la nouvelle fonctionnalité Incremental FS à la branche android-12-5.10 , qui inclut la mise à jour de la liste des symboles et de la représentation XML ABI.

  • Un exemple de changement de fonctionnalité se trouve dans aosp/1345659 .
  • Un exemple de liste de symboles se trouve dans aosp/1346742 .
  • L'exemple de modification ABI XML se trouve dans aosp/1349377 .

Si le symbole est exporté (soit par vous, soit s'il a été précédemment exporté) mais qu'aucun autre pilote ne l'utilise, vous pourriez obtenir une erreur de construction similaire à 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 ce problème, mettez à jour la liste des symboles KMI dans votre noyau et dans l'ACK (voir Mettre à jour la représentation ABI ). Pour un exemple de mise à jour du XML ABI et de la liste des symboles dans l'ACK, reportez-vous à aosp/1367601 .

Résoudre les pannes ABI du noyau

Vous pouvez gérer les pannes ABI du noyau en refactorisant le code pour ne pas modifier l'ABI ou en mettant à jour la représentation ABI . Utilisez le tableau suivant pour déterminer la meilleure approche pour votre situation.

Organigramme de rupture ABI

Figure 1. Résolution des cassures ABI

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

Faites tous les efforts possibles 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 de structure. Si un changement modifie l'ABI pour une fonctionnalité de débogage, ajoutez un #ifdef autour des champs (dans les structures et les références source) et assurez-vous que la CONFIG utilisée pour le #ifdef est désactivée pour la production defconfig et gki_defconfig . Pour un exemple de la façon dont une configuration de débogage peut être ajoutée à une structure sans casser l'ABI, reportez-vous à cet ensemble de correctifs .

  • Fonctionnalités de refactorisation pour ne pas modifier le noyau principal. Si de nouvelles fonctionnalités doivent être ajoutées à ACK pour prendre en charge les modules partenaires, essayez de refactoriser la partie ABI du changement pour éviter de modifier l'ABI du noyau. Pour un exemple d'utilisation de l'ABI du noyau existant pour ajouter des fonctionnalités supplémentaires sans modifier l'ABI du noyau, reportez-vous à aosp/1312213 .

Réparer un ABI cassé sur Android Gerrit

Si vous n'avez pas intentionnellement cassé l'ABI du noyau, vous devez alors enquêter, en utilisant les conseils fournis par l'outil de surveillance ABI. Les causes les plus courantes de pannes sont les modifications des structures de données et les modifications du symbole CRC associées, ou les modifications des options de configuration qui conduisent à l'un des éléments susmentionnés. Commencez par résoudre les problèmes détectés par l’outil.

Vous pouvez reproduire les résultats ABI localement, voir Construire le noyau et sa représentation ABI .

À propos des étiquettes Lint-1

Si vous téléchargez des modifications vers une branche contenant un KMI gelé ou finalisé, les modifications doivent passer par AbiAnalyzer pour garantir que les modifications n'affectent pas l'ABI stable de manière incompatible. Au cours de ce processus, AbiAnalyzer recherche le rapport ABI créé lors de la construction (une construction étendue qui effectue la construction normale, puis certaines étapes d'extraction et de comparaison ABI.

Si AbiAnalyzer trouve un rapport non vide, il définit l'étiquette Lint-1 et la modification est bloquée jusqu'à ce qu'elle soit résolue ; jusqu'à ce que l'ensemble de correctifs reçoive une étiquette Lint+1.

Mettre à jour l'ABI du noyau

Si la modification de l'ABI est inévitable, vous devez alors appliquer vos modifications de code, la représentation ABI et la liste de symboles à l'ACK. Pour que Lint supprime le -1 et ne rompe pas la compatibilité GKI, procédez comme suit :

  1. Téléchargez les modifications du code dans l'ACK .

  2. Attendez de recevoir un Code-Review +2 pour le patchset.

  3. Mettre à jour la représentation ABI de référence .

  4. Fusionnez vos modifications de code et la modification de la mise à jour ABI.

Télécharger les modifications du code ABI dans l'ACK

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

  • Si une modification ABI est liée à une fonctionnalité qui affecte les tests CTS ou VTS, la modification peut généralement être sélectionnée en ACK telle quelle. Par exemple:

  • Si une modification ABI concerne une fonctionnalité qui peut être partagée avec l'ACK, cette modification peut être sélectionnée telle quelle pour ACK. Par exemple, les modifications suivantes ne sont pas nécessaires pour le test CTS ou VTS, mais peuvent être partagées avec ACK :

  • Si une modification ABI introduit une nouvelle fonctionnalité qui n'a pas besoin d'être incluse dans l'ACK, vous pouvez introduire les symboles dans l'ACK à l'aide d'un stub comme décrit dans la section suivante.

Utiliser des stubs pour ACK

Les stubs doivent être nécessaires uniquement pour les modifications principales du noyau qui ne profitent pas à l'ACK, telles que les modifications de performances et de puissance. La liste suivante détaille des exemples de stubs et de sélections partielles dans ACK pour GKI.

  • Talon de fonctionnalité Core-isolat ( aosp/1284493 ). La fonctionnalité dans ACK n'est pas nécessaire, mais les symboles doivent être présents dans ACK pour que vos modules utilisent ces symboles.

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

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

  • Sélection partielle des modifications ABI de la structure thermique qui nécessitaient plus que le simple ajout de nouveaux champs ABI.

    • Le correctif aosp/1255544 a résolu les différences ABI entre le noyau partenaire et ACK.

    • Le correctif aosp/1291018 a résolu les problèmes fonctionnels détectés lors des tests GKI du correctif précédent. Le correctif comprenait l'initialisation de la structure des 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 ABI et a veillé à ce que les champs supplémentaires n'entraînent pas de différences fonctionnelles, permettant aux partenaires d'inclure CONFIG_NL80211_TESTMODE dans leurs noyaux de production tout en maintenant 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 répertoriés dans 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 construction et les entrées manquantes sont signalées.

À des fins de développement, vous pouvez utiliser une version du noyau GKI qui n'inclut pas la suppression des symboles (ce qui signifie que tous les symboles habituellement exportés peuvent être utilisés). Pour localiser ces versions, recherchez les versions kernel_debug_aarch64 sur ci.android.com .

Appliquer le KMI à l'aide du versioning de module

Les noyaux Generic Kernel Image (GKI) utilisent la gestion des versions de module ( CONFIG_MODVERSIONS ) comme mesure supplémentaire pour garantir la conformité KMI au moment de l'exécution. La gestion des versions de module peut provoquer des échecs de non-concordance du contrôle de redondance cyclique (CRC) au moment du chargement du module si le KMI attendu d'un module ne correspond pas au KMI vmlinux . Par exemple, ce qui suit est un échec typique qui se produit au moment du chargement du module en raison d'une incompatibilité 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 du versioning de module

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

  • La gestion des versions des modules détecte les changements dans la visibilité de la structure des données. Si les modules modifient des structures de données opaques, c'est-à-dire des structures de données qui ne font pas partie du KMI, elles se brisent après de futures modifications de la structure.

    À titre d'exemple, considérons le 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 ou faire des hypothèses sur sa taille.

    Cependant, si un module inclut <linux/fwnode.h> (directement ou indirectement), alors le champ fwnode dans le struct device ne lui est plus opaque. Le module peut ensuite apporter des modifications à device->fwnode->dev ou device->fwnode->ops . Ce scénario est problématique pour plusieurs raisons, énoncées comme suit :

    • Cela peut briser les hypothèses formulées par le code principal du noyau concernant ses structures de données internes.

    • Si une future mise à jour du noyau modifie la struct fwnode_handle (le type de données de fwnode ), alors le module ne fonctionne plus avec le nouveau noyau. De plus, stgdiff ne montrera aucune différence car le module brise le KMI en manipulant directement les structures de données internes d'une manière qui ne peut pas être capturée en inspectant uniquement la représentation binaire.

  • Un module actuel est considéré comme incompatible avec KMI lorsqu'il est chargé ultérieurement par un nouveau noyau incompatible. La gestion des versions de module ajoute une vérification à l'exécution pour é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 pannes du noyau qui pourraient résulter d'une incompatibilité non détectée dans le KMI.

L'activation du contrôle de version du module évite tous ces problèmes.

Vérifiez les incompatibilités CRC sans démarrer l'appareil

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

De plus, une construction complète du noyau avec CONFIG_MODVERSIONS activé génère un fichier Module.symvers dans le cadre du processus de construction normal. Ce fichier contient 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 du vmlinux ou du module qui exporte le symbole et le type d'exportation (par exemple, EXPORT_SYMBOL versus EXPORT_SYMBOL_GPL ).

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

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

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

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

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

Résoudre les incompatibilités CRC

Utilisez les étapes suivantes pour résoudre une incompatibilité CRC lors du chargement d'un module :

  1. Créez le noyau GKI et le noyau 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 . Voir KBUILD_SYMTYPES dans Kleaf pour plus de détails.

    Pour Android 13 et versions antérieures, créez le noyau GKI et le noyau de votre appareil en ajoutant KBUILD_SYMTYPES=1 à la commande que vous utilisez pour créer le noyau, comme indiqué dans la commande suivante :

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

    Lors de l'utilisation build_abi.sh, l'indicateur KBUILD_SYMTYPES=1 est déjà implicitement défini.

  2. Recherchez le fichier .c dans lequel le symbole avec incompatibilité 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 contient un fichier .symtypes correspondant dans la GKI et les artefacts de construction du noyau de votre appareil. Localisez 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 d'une ligne (potentiellement très longue) par symbole.

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

      t#bool typedef _Bool bool
      
    • Un préfixe # manquant au début de la ligne indique que le symbole est une fonction. Par 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 garde un symbole ou un type de données opaque pour les modules et que l'autre noyau ne le fait pas, cette différence apparaît entre les fichiers .symtypes des deux noyaux. Le fichier .symtypes de l'un des noyaux a UNKNOWN pour un symbole et le fichier .symtypes de l'autre noyau a une vue étendue du symbole ou du type de données.

Par exemple, l'ajout de la ligne suivante au fichier include/linux/device.h dans votre noyau provoque des incompatibilités CRC, dont l'une concerne module_layout() :

 #include <linux/fwnode.h>

La comparaison du module.symtypes pour ce symbole expose les différences suivantes :

 $ 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 noyau a une valeur UNKNOWN et que le noyau GKI a la vue étendue du symbole (très peu probable), fusionnez le dernier noyau commun Android dans votre noyau afin d'utiliser la dernière base de noyau GKI.

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

Souvent, la solution est aussi simple que de cacher le nouveau #include de genksyms .

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

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

  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 la 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 présentant une incompatibilité CRC, ajoutez ce qui suit comme première ligne avant l'une des lignes #include .

    #define CRC_CATCH 1
    
  4. Compilez votre module. L'erreur de construction qui en résulte montre la chaîne du fichier d'en-tête #include qui a conduit à cette incompatibilité CRC. Par 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 manque dans le noyau GKI.

  5. Identifiez la modification, rétablissez-la dans votre noyau ou téléchargez-la sur ACK et fusionnez-la .

Cas 2 : différences dues aux changements de type de données

Si l'inadéquation du CRC pour un symbole ou un type de données n'est pas due à une différence de visibilité, elle est alors due à des modifications réelles (ajouts, suppressions ou modifications) dans le type de données lui-même.

Par exemple, effectuer la modification suivante dans votre noyau provoque plusieurs incompatibilités 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);

Une incompatibilité CRC concerne devm_of_platform_populate() .

Si vous comparez les fichiers .symtypes pour ce symbole, cela pourrait ressembler à ceci :

 $ 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 des fichiers .h ).

    • Pour de simples différences de symboles entre votre noyau et le noyau GKI, recherchez le commit en exécutant la commande suivante :
    git blame
    
    • Pour les symboles supprimés (lorsqu'un symbole est supprimé dans une arborescence et que vous souhaitez également le supprimer dans l'autre arborescence), vous devez rechercher la modification qui a supprimé la ligne. Utilisez la commande suivante sur l'arborescence où la ligne a été supprimée :
    git log -S "copy paste of deleted line/word" -- <file where it was deleted>
    
  2. Examinez la liste des validations renvoyée pour localiser la modification ou la suppression. Le premier commit est probablement celui que vous recherchez. Si ce n'est pas le cas, parcourez la liste jusqu'à ce que vous trouviez le commit.

  3. Après avoir identifié le changement, rétablissez-le dans votre noyau ou téléchargez-le sur ACK et fusionnez-le .