Android-Kernel-ABI-Monitoring

Sie können die ABI-Monitoring-Tools (Application Binary Interface) verwenden, die in Android 11 und höher verfügbar sind, um die In-Kernel-ABI von Android-Kerneln zu stabilisieren. Das Tool sammelt und vergleicht ABI-Darstellungen aus vorhandenen Kernel-Binärdateien (vmlinux + GKI-Module). Diese ABI Darstellungen sind die .stg-Dateien und die Symbollisten. Die Benutzeroberfläche auf die durch die Darstellung eine Ansicht liefert, wird als Kernel Module Interface bezeichnet. (KMI). Mit den Tools können Sie Änderungen an der KMI verfolgen und abmildern.

Die Tools zur ABI-Überwachung entwickelt in AOSP und verwendet STG (oder libabigail in Android 13 und niedriger), um Daten zu generieren und zu vergleichen Darstellungen.

Auf dieser Seite werden die Tools, der Prozess zum Erfassen und Analysieren von ABI, beschrieben. Darstellungen sowie die Verwendung dieser Darstellungen, um die Stabilität der das ABI im Kernel. Auf dieser Seite finden Sie auch Informationen dazu, wie Sie Änderungen an den Android-Kerneln vornehmen können.

Prozess

Die Analyse des ABI des Kernels umfasst mehrere Schritte, von denen die meisten automatisiert werden können:

  1. Erstellen Sie den Kernel und seine ABI-Darstellung.
  2. ABI-Unterschiede zwischen dem Build und einer Referenz analysieren
  3. Aktualisieren Sie die ABI-Darstellung (falls erforderlich).
  4. Mit Symbollisten arbeiten

Die folgende Anleitung gilt für jeden Kernel, den Sie mit einer unterstützten Toolchain erstellen können, z. B. mit der vorgefertigten Clang-Toolchain. repo manifests sind für alle gängigen Android-Kernel-Branches und für mehrere gerätespezifische Kernel verfügbar. Sie sorgen dafür, dass beim Erstellen einer Kernel-Distribution für die Analyse die richtige Toolchain verwendet wird.

Symbollisten

Das KMI enthält nicht alle Symbole im Kernel oder sogar nicht alle der über 30.000 exportierten Symbole. Stattdessen können die Anbietermodule die folgenden Symbole verwenden: explizit in einer Reihe von Symbollistendateien aufgeführt sind, die öffentlich im Stammverzeichnis verwaltet werden. des Kernel-Baums. Die Vereinigung aller Symbole in allen Symbollistendateien definiert die als stabil gehaltenen KMI-Symbole. Ein Beispiel für eine Symbollistendatei ist abi_gki_aarch64_db845c, die die für das DragonBoard 845c erforderlichen Symbole deklariert.

Nur die in einer Symbolliste aufgeführten Symbole und die zugehörigen Strukturen und Definitionen gelten als Teil des KMI. Sie können Änderungen hochladen in Ihrem wenn die benötigten Symbole nicht vorhanden sind. Wenn neue Benutzeroberflächen verfügbar sind und Teil der KMI-Beschreibung sind, bleiben sie stabil, und dürfen nicht aus der Symbolliste entfernt oder nach der Erstellung des Zweigs geändert werden. eingefroren.

Jeder KMI-Kernel-Zweig des Android Common Kernel (ACK) hat seine eigenen Symbollisten. Es wird nicht versucht, ABI-Stabilität zwischen verschiedenen KMI-Kernels zu ermöglichen Zweige. Die KMI für android12-5.10 ist beispielsweise völlig unabhängig von die KMI für android13-5.10.

ABI-Tools verwenden KMI-Symbollisten, um einzuschränken, welche Schnittstellen überwacht werden müssen Stabilität. Die Hauptsymbolliste enthält die Symbole, die von den GKI-Kernelmodulen benötigt werden. Zulieferunternehmen zusätzliche Symbollisten einreichen und aktualisieren, um sicherzustellen, Sie benötigen die ABI-Kompatibilität der Schnittstellen, auf die sie angewiesen sind. Eine Liste der Symbollisten für die android13-5.15 finden Sie beispielsweise unter https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android.

Eine Symbolliste enthält die Symbole, die für den jeweiligen Anbieter oder das jeweilige Gerät erforderlich sind. Die vollständige Liste, die von den Tools verwendet wird, ist die Vereinigung aller KMI-Symbollistendateien. ABI-Tools ermitteln die Details jedes Symbols, einschließlich Funktionssignatur und verschachtelter Datenstrukturen.

Wenn das KMI eingefroren ist, sind keine Änderungen an den vorhandenen KMI-Schnittstellen zulässig. Sie sind stabil. Anbieter dürfen der KMI jedoch jederzeit Symbole hinzufügen. solange Ergänzungen die Stabilität des bestehenden ABI nicht beeinträchtigen. Neu hinzugefügte Symbole werden so lange als stabil betrachtet, bis sie in einer KMI-Symbolliste aufgeführt sind. Symbole sollten nur dann aus einer Liste für einen Kernel entfernt werden, wenn dies bestätigt werden kann. dass noch nie ein Gerät mit einer Abhängigkeit von diesem Symbol geliefert wurde.

Sie können eine KMI-Symbolliste für ein Gerät erstellen. Folgen Sie dazu der Anleitung unter Informationen zur Verwendung von Symbollisten Viele Partner reichen eine Symbolliste pro ACK ein, dies ist jedoch keine zwingende Anforderung. Wenn dies bei der Wartung hilft, können Sie mehrere Symbollisten einreichen.

KMI verlängern

KMI-Symbole und zugehörige Strukturen bleiben stabil, d. h. Änderungen, die stabile Schnittstellen in einem Kernel mit einem eingefrorenen KMI beeinträchtigen, können nicht akzeptiert werden. Der GKI-Kernel bleibt jedoch für Erweiterungen offen, sodass Geräte, die später im Jahr auf den Markt kommen, nicht alle ihre Abhängigkeiten definieren müssen, bevor das KMI eingefroren wird. Sie können dem KMI neue Symbole für neue oder vorhandene exportierte Kernelfunktionen hinzufügen, auch wenn das KMI eingefroren ist. Neue Kernel-Patches können auch akzeptiert werden, wenn sie die KMI nicht beeinträchtigen.

KMI-Unterbrechungen

Ein Kernel hat Quellen und Binärdateien werden aus diesen Quellen erstellt. ABI-überwachte Kernelzweige enthalten eine ABI-Darstellung des aktuellen GKI-ABI (in Form einer .stg-Datei). Nachdem die Binärdateien (vmlinux, Image und alle GKI-Module) erstellt wurden, kann eine ABI-Darstellung aus den Binärdateien extrahiert werden. Jede Änderung an einer Kernel-Quelldatei kann sich auf die Binärdateien und damit auch auf die extrahierte .stg auswirken. Der AbiAnalyzer-Analysator vergleicht die committete .stg-Datei mit der aus den Build-Artefakten extrahierten und setzt in Gerrit ein Lint-1-Label auf die Änderung, wenn er einen semantischen Unterschied findet.

Umgang mit ABI-Unterbrechungen

Der folgende Patch führt beispielsweise zu einem sehr offensichtlichen ABI-Fehler:

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.

Wenn Sie das Build-ABI mit diesem Patch ausführen, wird das Tool mit einem Fehlercode ungleich null beendet und meldet eine ABI-Unterscheidung, die in etwa so aussieht:

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

Beim Build-Zeitpunkt festgestellte ABI-Unterschiede

Der häufigste Grund für Fehler ist, wenn ein Fahrer ein neues Symbol aus der der nicht in einer der Symbollisten enthalten ist.

Wenn das Symbol nicht in der Symbolliste (android/abi_gki_aarch64) enthalten ist, müssen Sie zuerst prüfen, ob es mit EXPORT_SYMBOL_GPL(symbol_name) exportiert wurde, und dann die ABI-XML-Darstellung und die Symbolliste aktualisieren. Mit den folgenden Änderungen wird beispielsweise die neue Funktion „Incremental FS“ dem android-12-5.10-Branch hinzugefügt. Dazu gehört auch die Aktualisierung der Symbolliste und der ABI-XML-Darstellung.

  • Ein Beispiel für eine Änderungsbeschreibung finden Sie unter aosp/1345659.
  • Ein Beispiel für eine Symbolliste finden Sie unter aosp/1346742.
  • Das Beispiel für eine ABI-XML-Änderung befindet sich in aosp/1349377

Wenn das Symbol exportiert wurde (entweder von Ihnen oder zuvor), aber nicht verwendet wird, erhalten Sie möglicherweise einen Build-Fehler wie den folgenden.

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

Aktualisieren Sie die KMI-Symbolliste sowohl im Kernel als auch im ACK, um das Problem zu beheben (siehe ABI-Darstellung aktualisieren). Beispiel der ABI-XML und der Symbolliste in der ACK erhalten Sie unter aosp/1367601

Kernel-ABI-Ausfälle beheben

Sie können Kernel-ABI-Ausfälle beheben, indem Sie den Code so refaktorieren, dass die ABI oder die ABI-Darstellung aktualisieren Verwenden Sie Folgendes: Diagramm, um den besten Ansatz für Ihre Situation zu ermitteln.

Flussdiagramm zum ABI-Ausbruch

Abbildung 1. Fehlerbehebung bei Problemen mit ABI

Code umschreiben, um ABI-Änderungen zu vermeiden

Ändern Sie das vorhandene ABI nach Möglichkeit nicht. In vielen Fällen können Sie Ihren Code refaktorieren, um Änderungen zu entfernen, die sich auf das ABI auswirken.

  • Änderungen des Strukturfelds refaktorieren: Wenn eine Änderung das ABI für eine Fehlerbehebung ändert fügen Sie einen #ifdef um die Felder (in den Strukturen und der Quelle) Referenzen) und achten Sie darauf, dass die für #ifdef verwendete CONFIG für Production defconfig und gki_defconfig Ein Beispiel für eine Fehlerbehebung Konfiguration kann einer Struktur hinzugefügt werden, ohne das ABI zu unterbrechen. Weitere Informationen patchset

  • Funktionen umstrukturieren, um den Kern nicht zu ändern Wenn ACK neue Funktionen hinzugefügt werden müssen, um die Partnermodule zu unterstützen, versuchen Sie, den ABI-Teil der Änderung zu überarbeiten, um die Änderung des Kernel-ABI zu vermeiden. Ein Beispiel dafür, wie Sie mit dem vorhandenen Kernel-ABI zusätzliche Funktionen hinzufügen, ohne das Kernel-ABI zu ändern, finden Sie unter aosp/1312213.

Fehlerhafte ABIs in Android Gerrit beheben

Wenn Sie den Kernel-ABI nicht absichtlich durchbrochen haben, müssen Sie ihn untersuchen, anhand der Vorgaben der ABI-Monitoringtools. Die häufigsten Ursachen für Unterbrechungen sind geänderte Datenstrukturen und die zugehörigen Symbol-CRC-Änderungen oder Änderungen an Konfigurationsoptionen, die zu einer der oben genannten Änderungen führen. Beheben Sie zuerst die vom Tool gefundenen Probleme.

Sie können die ABI-Ergebnisse lokal reproduzieren. Weitere Informationen finden Sie unter Kernel und ABI-Darstellung erstellen.

Lint-1-Labels

Wenn Sie Änderungen an einem Zweig hochladen, der eine eingefrorene oder abgeschlossene KMI enthält, Änderungen müssen den AbiAnalyzer übergeben, damit sie sich nicht auf die stabile Version auswirken ABI nicht kompatibel ist. Während dieses Vorgangs sucht AbiAnalyzer nach dem ABI-Bericht, der während des Build-Prozesses erstellt wird (ein erweiterter Build, der den normalen Build und dann einige ABI-Extraktions- und Vergleichsschritte.

Wenn AbiAnalyzer einen nicht leeren Bericht findet, werden das Lint-1-Label und die Die Änderung kann erst eingereicht werden, wenn sie behoben ist. bis das Patch-Set eine Lint+1-Label.

Kernel-ABI aktualisieren

Wenn die Änderung des ABI unvermeidlich ist, müssen Sie Ihre Codeänderungen, die ABI-Darstellung und die Symbolliste auf die ACK anwenden. Damit Lint Entfernen Sie „-1“, ohne die GKI-Kompatibilität zu beeinträchtigen, und gehen Sie so vor:

  1. Codeänderungen für die Bestätigung hochladen

  2. Warten Sie, bis Sie eine Code-Review +2 für das Patchset erhalten.

  3. Aktualisieren Sie die ABI-Referenzdarstellung.

  4. Führen Sie Ihre Codeänderungen und die ABI-Aktualisierungsänderung zusammen.

ABI-Codeänderungen in die ACK hochladen

Die Aktualisierung der ACK ABI hängt von der Art der vorgenommenen Änderung ab.

  • Wenn eine ABI-Änderung mit einer Funktion zusammenhängt, die sich auf CTS- oder VTS-Tests auswirkt, Änderung kann in der Regel selektiv zum Bestätigen bestätigt werden. Hier einige Beispiele:

  • Wenn eine ABI-Änderung für eine Funktion gilt, die mit dem ACK geteilt werden kann, kann diese Änderung unverändert in das ACK übernommen werden. Die folgenden Änderungen sind beispielsweise für CTS- oder VTS-Tests nicht erforderlich, können aber mit dem ACK geteilt werden:

  • Wenn durch eine ABI-Änderung eine neue Funktion eingeführt wird, die nicht in ACK enthalten sein muss, können Sie die Symbole mithilfe eines Symbolstups in ACK einfügen, wie im folgenden Abschnitt beschrieben.

Stubs für ACK verwenden

Stubs dürfen nur für Kerneländerungen erforderlich sein, die dem ACK nicht zugutekommen, z. B. Leistungs- und Energieänderungen. In der folgenden Liste finden Sie Beispiele für Stubs und teilweise Cherry-Picks in ACK für GKI.

  • Stub für die Core-Isolate-Funktion (aosp/1284493). Die Funktionen in ACK sind nicht erforderlich, aber die Symbole müssen vorhanden sein. in ACK, damit Ihre Module diese Symbole verwenden.

  • Platzhaltersymbol für Anbietermodul (aosp/1288860)

  • ABI-spezifische Auswahl der mm-Ereignis-Tracking-Funktion pro Prozess (aosp/1288454). Das ursprüngliche Patch wurde sorgfältig ausgewählt und dann so zugeschnitten, dass es nur die notwendigen Änderungen, um den ABI-Differenz für task_struct und mm_event_count. Dieser Patch aktualisiert auch die Aufzählung mm_event_type so, dass sie Folgendes enthält: den Endmitgliedern gerecht zu werden.

  • Teilweise ABI-Änderungen der Thermalstruktur, die mehr erforderten als nur die neuen ABI-Felder.

    • Der Patch aosp/1255544 behebt ABI-Unterschiede zwischen dem Partnerkernel und ACK.

    • Pflaster aosp/1291018 Wir haben die Funktionsprobleme behoben, die bei den GKI-Tests des vorherigen Patches festgestellt wurden. Zur Problembehebung wurde die zu registrierende Sensorparameterstruktur initialisiert mit einem Sensor verbinden.

  • CONFIG_NL80211_TESTMODE ABI-Änderungen (aosp/1344321) Mit diesem Patch wurden die notwendigen Strukturänderungen für ABI hinzugefügt und zusätzliche Felder keine Funktionsunterschiede, sodass Partner CONFIG_NL80211_TESTMODE in ihre Produktions-Kernel aufzunehmen und trotzdem GKI-Compliance aufrechterhalten

KMI während der Laufzeit erzwingen

Die GKI-Kernel verwenden die Konfigurationsoptionen TRIM_UNUSED_KSYMS=y und UNUSED_KSYMS_WHITELIST=<union of all symbol lists>, mit denen die exportierten Symbole (z. B. Symbole, die mit EXPORT_SYMBOL_GPL() exportiert wurden) auf diejenigen in einer Symbolliste beschränkt werden. Alle anderen Symbole sind nicht exportiert und das Laden eines Moduls, das ein nicht exportiertes Symbol erfordert, wird abgelehnt. Diese Einschränkung wird zum Zeitpunkt des Builds erzwungen und fehlende Einträge werden gemeldet.

Für Entwicklungszwecke können Sie einen GKI-Kernel-Build verwenden, der keine Symbolbeschneidung enthält. Das bedeutet, dass alle normalerweise exportierten Symbole verwendet werden können. Sie finden diese Builds unter ci.android.com.

KMI mithilfe der Modulversionierung erzwingen

Die GKI-Kernel (Generic Kernel Image) verwenden die Modulversionierung (CONFIG_MODVERSIONS) als zusätzliche Maßnahme, um die KMI-Compliance zur Laufzeit durchzusetzen. Die Modulversionsverwaltung kann zu einer Abweichung bei der zyklischen Redundanzprüfung (Cyclic Redundant Check, CRC) führen Fehler beim Laden des Moduls, wenn die erwartete KMI eines Moduls nicht mit dem vmlinux KMI. Das folgende Beispiel zeigt einen typischen Fehler, der beim Laden des Moduls aufgrund einer CRC-Nichtübereinstimmung für das Symbol module_layout() auftritt:

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 ''

Verwendung der Modulversionsverwaltung

Die Modulversionsverwaltung ist aus folgenden Gründen nützlich:

  • Mit der Modulversionierung werden Änderungen an der Sichtbarkeit der Datenstruktur erfasst. Wenn-Module undurchsichtige Datenstrukturen zu ändern, also Datenstrukturen, KMI, brechen sie nach zukünftigen Änderungen der Struktur ab.

    Betrachten Sie beispielsweise das Feld fwnode in struct device. Dieses Feld MUSS für Module undurchsichtig sein, damit sie keine Änderungen an Feldern von device->fw_node vornehmen oder Annahmen über deren Größe treffen können.

    Wenn ein Modul jedoch <linux/fwnode.h> (direkt oder indirekt) enthält, ist das Feld fwnode in struct device für dieses Modul nicht mehr undurchsichtig. Das Modul kann dann Änderungen an device->fwnode->dev oder device->fwnode->ops vornehmen. Dieses Szenario ist aus mehreren Gründen problematisch, wie folgt angegeben:

    • Das kann Annahmen des Kernel-Kerncodes über seine internen Datenstrukturen aufheben.

    • Wenn bei einem zukünftigen Kernelupdate die struct fwnode_handle (der Datentyp von fwnode) geändert wird, funktioniert das Modul nicht mehr mit dem neuen Kernel. Außerdem zeigt stgdiff keine Unterschiede, da das Modul die KMI verletzt, indem es interne Datenstrukturen direkt auf eine Weise manipuliert, die nicht durch bloße Prüfung der Binärdarstellung erfasst werden kann.

  • Ein aktuelles Modul gilt als nicht mit KMI kompatibel, wenn es zu einem späteren Zeitpunkt von einem neuen, nicht kompatiblen Kernel geladen wird. Durch die Modulversionsverwaltung wird Vermeiden Sie es, versehentlich ein Modul zu laden, das nicht mit dem Kernel kompatibel ist. Diese Prüfung verhindert schwer zu behebende Laufzeitprobleme und Kernel-Abstürze, die durch eine nicht erkannte Inkompatibilität in der KMI verursacht werden können.

Wenn Sie die Modulversionsverwaltung aktivieren, können diese Probleme vermieden werden.

Nach CRC-Abweichungen suchen, ohne das Gerät zu starten

stgdiff vergleicht und meldet CRC-Abweichungen zwischen Kerneln und anderen ABI-Unterschiede.

Außerdem wird bei einem vollständigen Kernel-Build mit aktivierter CONFIG_MODVERSIONS-Option im Rahmen des normalen Build-Prozesses eine Module.symvers-Datei generiert. Diese Datei enthält eine für jedes Symbol, das vom Kernel (vmlinux) und den Modulen exportiert wurde. Jedes besteht aus dem CRC-Wert, dem Symbolnamen, dem Symbol-Namespace, dem vmlinux- oder Modulname, in dem das Symbol exportiert wird, und der Exporttyp (z. B. EXPORT_SYMBOL gegen EXPORT_SYMBOL_GPL).

Sie können die Module.symvers-Dateien des GKI-Builds mit Ihrem Build vergleichen. um nach CRC-Unterschieden in den von vmlinux exportierten Symbolen zu suchen. Wenn der CRC-Wert eines Symbols, das mit vmlinux und exportiert wurde, von einem der Module abweicht, das Sie auf Ihr Gerät laden, wird das Modul nicht geladen.

Wenn Sie nicht alle Build-Artefakte haben, aber die vmlinux-Dateien des GKI-Kernels und Ihres Kernels, können Sie die CRC-Werte für ein bestimmtes Symbol vergleichen. Führen Sie dazu den folgenden Befehl auf beiden Kerneln aus und vergleichen Sie die Ausgabe:

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

Mit dem folgenden Befehl wird beispielsweise der CRC-Wert für module_layout geprüft. Symbol:

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

CRC-Abweichungen beheben

So beheben Sie eine CRC-Nichtübereinstimmung beim Laden eines Moduls:

  1. Erstellen Sie den GKI-Kernel und den Gerätekernel mit der Option --kbuild_symtypes, wie im folgenden Befehl gezeigt:

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

    Mit diesem Befehl wird für jede .o-Datei eine .symtypes-Datei generiert. Weitere Informationen finden Sie unter KBUILD_SYMTYPES in Kleaf .

    Erstellen Sie für Android 13 und niedriger den GKI-Kernel. und Ihren Geräte-Kernel, indem Sie KBUILD_SYMTYPES=1 dem Befehl verwenden, um den Kernel zu erstellen, wie im folgenden Befehl gezeigt:

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

    Wenn Sie build_abi.sh, verwenden, ist das Flag KBUILD_SYMTYPES=1 bereits implizit gesetzt.

  2. Suchen Sie mit dem folgenden Befehl nach der .c-Datei, in der das Symbol mit CRC-Nichtübereinstimmung exportiert wurde:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
  3. Die .c-Datei hat eine entsprechende .symtypes-Datei in der GKI und Ihre Build-Artefakte für den Gerätekernel. Suchen Sie mit den folgenden Befehlen nach der .c-Datei:

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

    Die Datei .c hat folgende Merkmale:

    • Die Datei .c hat das Format einer (möglicherweise sehr langen) Zeile pro Symbol.

    • [s|u|e|etc]# am Anfang der Zeile bedeutet, dass das Symbol den Datentyp hat [struct|union|enum|etc]. Beispiel:

      t#bool typedef _Bool bool
      
    • Ein fehlendes #-Präfix am Anfang der Zeile gibt an, dass das Symbol eine Funktion ist. Beispiel:

      find_module s#module * find_module ( const char * )
      
  4. Vergleichen Sie die beiden Dateien und beheben Sie alle Unterschiede.

Fall 1: Unterschiede aufgrund der Sichtbarkeit des Datentyps

Wenn ein Kernel ein Symbol oder einen Datentyp für die Module undurchsichtig hält und der andere Kernel dies nicht tut, wird dieser Unterschied zwischen den .symtypes-Dateien der beiden Kernel angezeigt. Die Datei .symtypes von einem der Kernel enthält UNKNOWN. für ein Symbol und die Datei .symtypes aus dem anderen Kernel hat eine erweiterte Ansicht des Symbols oder Datentyps.

Fügen Sie beispielsweise die folgende Zeile zum Die Datei include/linux/device.h in Ihrem Kernel verursacht CRC-Abweichungen. Unter anderem ist für module_layout():

 #include <linux/fwnode.h>

Beim Vergleich der module.symtypes für dieses Symbol sind folgende Unterschiede zu erkennen:

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

Wenn Ihr Kernel den Wert UNKNOWN und der GKI-Kernel die erweiterte Ansicht hat des Symbols aus (sehr unwahrscheinlich), dann führen Sie den neuesten Android Common Kernel in Ihren Kernel, sodass Sie die neueste GKI-Kernel-Basis verwenden.

In den meisten Fällen hat der GKI-Kernel den Wert UNKNOWN, während Ihr Kernel den interne Details des Symbols aufgrund von Änderungen an Ihrem Kernel. Das liegt daran, dass einer der Dateien in Ihrem Kernel ein #include hinzugefügt wurde, das im GKI-Kernel nicht vorhanden ist.

Häufig wird das Problem dadurch behoben, dass der neue #include vor genksyms ausgeblendet wird.

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

Andernfalls können Sie so vorgehen, um die #include zu ermitteln, die den Unterschied verursacht:

  1. Öffnen Sie die Headerdatei, in der das Symbol oder der Datentyp definiert ist, Unterschied. Ändern Sie beispielsweise include/linux/fwnode.h in struct fwnode_handle.

  2. Fügen Sie oben in der Headerdatei den folgenden Code ein:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. Fügen Sie in der .c-Datei des Moduls mit einer CRC-Nichtübereinstimmung die folgende Zeile als erste Zeile vor allen #include-Zeilen hinzu.

    #define CRC_CATCH 1
    
  4. Kompilieren Sie Ihr Modul. Der resultierende Buildzeitfehler zeigt die Kette der Headerdatei #include, die zu dieser CRC-Nichtübereinstimmung geführt hat. Beispiel:

    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"
    

    Eines der Glieder in dieser Kette von #include ist auf eine Änderung an Ihrem das im GKI-Kernel fehlt.

  5. Identifizieren Sie die Änderung, kehren Sie sie in Ihrem Kernel rückgängig oder laden Sie sie in ACK hoch und lassen Sie sie zusammenführen.

Fall 2: Unterschiede aufgrund von Änderungen am Datentyp

Wenn die CRC-Nichtübereinstimmung für ein Symbol oder einen Datentyp nicht auf eine unterschiedliche Sichtbarkeit zurückzuführen ist, liegt dies an tatsächlichen Änderungen (Hinzufügungen, Entfernungen oder Änderungen) am Datentyp selbst.

Die folgende Änderung am Kernel führt beispielsweise zu mehreren CRC-Abweichungen, da viele Symbole indirekt von dieser Art von Änderung betroffen sind:

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

Eine CRC-Abweichung betrifft devm_of_platform_populate().

Wenn Sie die .symtypes-Dateien für dieses Symbol vergleichen, sieht das möglicherweise so aus:

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

So ermitteln Sie den geänderten Typ:

  1. Suchen Sie im Quellcode (normalerweise in .h-Dateien) nach der Definition des Symbols.

    • Wenn Sie Symbolunterschiede zwischen Ihrem Kernel und dem GKI-Kernel finden möchten, führen Sie den folgenden Befehl aus, um den Commit zu ermitteln:
    git blame
    • Für gelöschte Symbole (wenn ein Symbol in einem Baum gelöscht wird und Sie auch im anderen Baum löschen möchten), müssen Sie die Änderung suchen, hat die Zeile gelöscht. Führen Sie den folgenden Befehl in der Baumstruktur aus, in der sich die Zeile wurde gelöscht:
    git log -S "copy paste of deleted line/word" -- <file where it was deleted>
  2. Sehen Sie sich die zurückgegebene Liste der Commits an, um die Änderung oder das Löschen zu finden. Die ist wahrscheinlich derjenige, nach dem Sie suchen. Wenn nicht, gehen Sie die Liste durch, bis Sie den Commit finden.

  3. Nachdem Sie die Änderung gefunden haben, können Sie sie entweder in Ihrem Kernel rückgängig machen oder sie in ACK hochladen und zusammenführen lassen.