Sie können die Monitoringtools für Binärschnittstellen (Application Binary Interface, ABI) ab Android 11 verwenden, um das ABI im Kernel von Android-Kerneln zu stabilisieren. Das Tool erfasst und vergleicht ABI-Darstellungen aus vorhandenen Kernel-Binärdateien (vmlinux
+ GKI-Module). Diese ABI-Darstellungen sind die .stg
-Dateien und die Symbollisten. Die Schnittstelle, auf der die Darstellung angezeigt wird, wird als Kernel Module Interface (KMI) bezeichnet. Mit den Tools können Sie Änderungen an der KMI verfolgen und abmildern.
Die ABI-Monitoring-Tools werden in AOSP entwickelt und verwenden STG (oder libabigail
in Android 13 und niedriger), um Darstellungen zu generieren und zu vergleichen.
Auf dieser Seite werden die Tools, das Erfassen und Analysieren von ABI-Darstellungen sowie die Verwendung solcher Darstellungen zur Stabilisierung des In-Kernel-ABI beschrieben. 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:
- Erstellen Sie den Kernel und seine ABI-Darstellung.
- ABI-Unterschiede zwischen dem Build und einer Referenz analysieren
- Aktualisieren Sie die ABI-Darstellung (falls erforderlich).
- 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 gemeinsamen 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 werden die Symbole, die von Anbietermodulen verwendet werden können, explizit in einer Reihe von Symbollistendateien aufgeführt, die öffentlich im Stamm des Kernel-Baums verwaltet werden. Die Vereinigung aller Symbole in allen Symbollistendateien definiert die Gruppe der KMI-Symbole, die als stabil gilt. 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 an Ihren Symbollisten vornehmen, wenn die benötigten Symbole nicht vorhanden sind. Nachdem neue Schnittstellen in einer Symbolliste enthalten sind und Teil der KMI-Beschreibung sind, werden sie als stabil gepflegt und dürfen nach dem Einfrieren des Branches nicht aus der Symbolliste entfernt oder geändert werden.
Jeder KMI-Kernel-Zweig des Android Common Kernel (ACK) hat seine eigenen Symbollisten. Es wird nicht versucht, die ABI-Stabilität zwischen verschiedenen KMI-Kernel-Branches zu gewährleisten. Beispielsweise ist die KMI für android12-5.10
völlig unabhängig von der KMI für android13-5.10
.
ABI-Tools verwenden KMI-Symbollisten, um einzuschränken, welche Schnittstellen auf Stabilität überwacht werden müssen. Die Hauptsymbolliste enthält die Symbole, die für die GKI-Kernelmodule erforderlich sind. Anbieter müssen zusätzliche Symbollisten einreichen und aktualisieren, damit die von ihnen verwendeten Schnittstellen ABI-kompatibel bleiben. Eine Liste der Symbollisten für die android13-5.15
finden Sie 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 die KMI eingefroren ist, sind keine Änderungen an den vorhandenen KMI-Schnittstellen zulässig. Sie sind stabil. Anbieter können dem KMI jedoch jederzeit Symbole hinzufügen, solange die Stabilität des vorhandenen ABI dadurch nicht beeinträchtigt wird. 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 bestätigt werden kann, dass kein Gerät jemals mit einer Abhängigkeit von diesem Symbol ausgeliefert wurde.
Eine KMI-Symbolliste für ein Gerät können Sie mithilfe der Anleitung unter Mit Symbollisten arbeiten generieren. Viele Partner reichen eine Symbolliste pro ACK ein, dies ist jedoch keine zwingende Anforderung. Wenn es die Wartung erleichtert, können Sie mehrere Symbollisten einreichen.
KMI verlängern
Während KMI-Symbole und zugehörige Strukturen stabil bleiben (d. h. Änderungen, die stabile Schnittstellen in einem Kernel mit einer eingefrorenen KMI zerstören, können nicht akzeptiert werden), bleibt der GKI-Kernel Erweiterungen offen, sodass Geräte, die später im Jahr versendet werden, nicht alle ihre Abhängigkeiten definieren müssen, bevor der 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 aus diesen Quellen werden Binärdateien erstellt.
Von 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, die an einer Kernel-Quelldatei vorgenommen wird, kann sich auf die Binärdateien und im Gegenzug auch auf die extrahierten .stg
auswirken. Der AbiAnalyzer
-Analysator vergleicht die übergebene .stg
-Datei mit der Datei, die aus Build-Artefakten extrahiert wurde, und legt ein Lint-1-Label für die Änderung in Gerrit fest, wenn sie einen semantischen Unterschied findet.
Umgang mit ABI-Unterbrechungen
Der folgende Patch führt beispielsweise zu einer sehr offensichtlichen ABI-Unterbrechung:
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 den Build ABI mit diesem Patch ausführen, wird das Tool mit einem Fehlercode ungleich null beendet und meldet einen ABI-Unterschied ähnlich dem folgenden:
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
Bei der Buildzeit erkannte ABI-Unterschiede
Der häufigste Grund für Fehler ist, wenn ein Treiber ein neues Symbol aus dem Kernel verwendet, das in keiner 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 -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.
- Das Beispiel für eine Featureänderung finden Sie in aosp/1345659.
- Ein Beispiel für eine Symbolliste finden Sie unter aosp/1346742.
- Ein Beispiel für eine ABI-XML-Änderung finden Sie unter aosp/1349377.
Wenn das Symbol exportiert wird (entweder von Ihnen oder zuvor exportiert), aber von keinem anderen Treiber 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). Ein Beispiel für die Aktualisierung der ABI-XML und der Symbolliste in der ACK findest du unter aosp/1367601.
Kernel-ABI-Unterbrechungen beheben
Sie können Kernel-ABI-Ausfälle beheben, indem Sie den Code so refaktorieren, dass das ABI nicht geändert wird, oder die ABI-Darstellung aktualisieren. Anhand des folgenden Diagramms können Sie den für Ihre Situation am besten geeigneten Ansatz ermitteln.
Abbildung 1. Lösung bei ABI-Unterbrechungen
Code umschreiben, um ABI-Änderungen zu vermeiden
Ändern Sie die vorhandene ABI nach Möglichkeit nicht. In vielen Fällen können Sie Ihren Code refaktorisieren, um Änderungen zu entfernen, die sich auf das ABI auswirken.
Refactoring von Änderungen an Struct-Feldern Wenn durch eine Änderung das ABI für eine Debugfunktion geändert wird, setzen Sie in den Strukturen und Quellreferenzen
#ifdef
um die Felder herum und achten Sie darauf, dass die für#ifdef
verwendeteCONFIG
für die Produktions-Defconfig undgki_defconfig
deaktiviert ist. Ein Beispiel dafür, wie einer Struktur eine Debug-Konfiguration hinzugefügt werden kann, ohne die ABI zu verletzen, finden Sie in diesem Patch-Set.Refaktorierung von Funktionen, damit der Kern-Kernel nicht geändert wird. 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 das Kernel-ABI nicht absichtlich verletzt haben, müssen Sie die Ursache anhand der Anleitungen der ABI-Monitoring-Tools ermitteln. 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 in einen Branch hochladen, der eine eingefrorene oder finalisierte KMI enthält, müssen die Änderungen die AbiAnalyzer
bestehen, damit sie die stabile ABI nicht inkompatibel beeinflussen. Während dieses Vorgangs sucht AbiAnalyzer
nach dem ABI-Bericht, der während des Builds erstellt wird (ein erweiterter Build, bei dem der normale Build und dann einige ABI-Extraktions- und Vergleichsschritte ausgeführt werden).
Wenn AbiAnalyzer
einen nicht leeren Bericht findet, wird das Lint-1-Label festgelegt und die Änderung kann erst eingereicht werden, wenn das Problem behoben ist, also das Patch-Set das Lint+1-Label erhält.
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. So sorgen Sie dafür, dass Lint die -1 entfernt und die GKI-Kompatibilität nicht beeinträchtigt:
Warten Sie, bis Sie eine Code-Review +2 für das Patchset erhalten.
Führen Sie die Codeänderungen und die Änderung des ABI-Updates zusammen.
ABI-Codeänderungen in die ACK hochladen
Das Aktualisieren des ACK-ABI hängt von der Art der Änderung ab.
Wenn eine ABI-Änderung mit einer Funktion zusammenhängt, die sich auf CTS- oder VTS-Tests auswirkt, kann die Änderung in der Regel so übernommen werden, wie sie ist. Beispiele:
- aosp/1289677 ist erforderlich, damit das Audio funktioniert.
- aosp/1295945 ist erforderlich, damit USB funktioniert.
Wenn eine ABI-Änderung für ein Feature gilt, das mit der ACK freigegeben werden kann, kann diese Änderung in der vorliegenden Form zum Bestätigen ausgewählt werden. Die folgenden Änderungen sind beispielsweise nicht für CTS- oder VTS-Tests erforderlich, können aber mit ACK geteilt werden:
- aosp/1250412 ist eine Änderung an der Temperaturfunktion.
- aosp/1288857 ist eine
EXPORT_SYMBOL_GPL
-Änderung.
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.
Core-isolate-Funktions-Stub (aosp/1284493). Die Funktionen in ACK sind nicht erforderlich, aber die Symbole müssen in ACK vorhanden sein, damit Ihre Module diese Symbole verwenden können.
Platzhaltersymbol für Anbietermodul (aosp/1288860).
ABI-spezifische Auswahl der
mm
-Ereignis-Tracking-Funktion pro Prozess (aosp/1288454). Der ursprüngliche Patch wurde für die Bestätigung ausgewählt und dann so gekürzt, dass nur die erforderlichen Änderungen enthalten sind, um die ABI-Unterscheidung fürtask_struct
undmm_event_count
zu beheben. Mit diesem Patch wird auch dasmm_event_type
-Enum aktualisiert, sodass es die endgültigen Mitglieder enthält.Teilweise Auswahl von ABI-Änderungen an der Temperaturstruktur, für die nicht nur die neuen ABI-Felder hinzugefügt werden mussten.
Der Patch aosp/1255544 behebt ABI-Unterschiede zwischen dem Partnerkernel und ACK.
Mit dem Patch aosp/1291018 wurden die Funktionsprobleme behoben, die beim GKI-Test des vorherigen Patches festgestellt wurden. Die Korrektur umfasste die Initialisierung des Sensorparameter-Structs, um mehrere Wärmezonen für einen einzelnen Sensor zu registrieren.
CONFIG_NL80211_TESTMODE
ABI-Änderungen (aosp/1344321) Mit diesem Patch wurden die erforderlichen Strukturänderungen für das ABI hinzugefügt und dafür gesorgt, dass die zusätzlichen Felder keine funktionalen Unterschiede verursachen. So können PartnerCONFIG_NL80211_TESTMODE
in ihre Produktionskerne aufnehmen und gleichzeitig die GKI-Compliance aufrechterhalten.
KMI zur Laufzeit erzwingen
Die GKI-Kernel verwenden die Konfigurationsoptionen TRIM_UNUSED_KSYMS=y
und UNUSED_KSYMS_WHITELIST=<union
of all symbol lists>
, die die exportierten Symbole (z. B. mit EXPORT_SYMBOL_GPL()
exportierte Symbole) auf die in einer Symbolliste aufgeführten Symbole beschränken. 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 durchgesetzt und fehlende Einträge werden gekennzeichnet.
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.kernel_debug_aarch64
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 Modulversionierung kann zu CRC-Abweichungen (Cyclic Redundancy Check) beim Laden des Moduls führen, wenn die erwartete KMI eines Moduls nicht mit der vmlinux
-KMI übereinstimmt. 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 Modulversionsverwaltung werden Änderungen an der Sichtbarkeit der Datenstruktur erfasst. Wenn Module undurchsichtige Datenstrukturen ändern, also Datenstrukturen, die nicht Teil der KMI sind, funktionieren sie nach zukünftigen Änderungen an der Struktur nicht mehr.
Ein Beispiel hierfür ist das Feld
fwnode
instruct device
. Dieses Feld MUSS für Module undurchsichtig sein, damit sie keine Änderungen an Feldern vondevice->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 Feldfwnode
instruct device
für dieses Modul nicht mehr undurchsichtig. Das Modul kann dann Änderungen andevice->fwnode->dev
oderdevice->fwnode->ops
vornehmen. Dieses Szenario ist aus mehreren Gründen problematisch:Das kann Annahmen des Kernel-Kerncodes über seine internen Datenstrukturen aufheben.
Wenn bei einem zukünftigen Kernelupdate die
struct fwnode_handle
(der Datentyp vonfwnode
) geändert wird, funktioniert das Modul nicht mehr mit dem neuen Kernel. Außerdem zeigtstgdiff
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 Modulversionierung wird eine Laufzeitprüfung hinzugefügt, um zu verhindern, dass versehentlich ein Modul geladen wird, das nicht KMI-kompatibel mit dem Kernel ist. Durch diese Prüfung werden schwer zu behebende Laufzeitprobleme und Kernel-Abstürze verhindert, die auf eine nicht erkannte Inkompatibilität in der KMI zurückzuführen sein 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 CRC-Abweichungen zwischen Kernen und meldet diese sowie andere ABI-Unterschiede.
Außerdem wird bei einem vollständigen Kernel-Build mit aktivierter CONFIG_MODVERSIONS
-Funktion im Rahmen des normalen Build-Prozesses eine Module.symvers
-Datei generiert. Diese Datei enthält eine Zeile für jedes Symbol, das vom Kernel (vmlinux
) und den Modulen exportiert wurde. Jede Zeile besteht aus dem CRC-Wert, dem Symbolnamen, dem Symbol-Namespace, dem vmlinux
- oder Modulnamen, über den das Symbol exportiert wird, und dem Exporttyp (z. B. EXPORT_SYMBOL
oder EXPORT_SYMBOL_GPL
).
Sie können die Module.symvers
-Dateien des GKI-Builds mit denen Ihres Builds vergleichen, um nach CRC-Unterschieden in den von vmlinux
exportierten Symbolen zu suchen. Wenn es eine CRC-Wertdifferenz in einem von vmlinux
exportierten Symbol gibt und dieses Symbol von einem der Module verwendet wird, die Sie in 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 das Symbol module_layout
geprüft:
nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout
CRC-Abweichungen beheben
So beheben Sie einen CRC-Nichtübereinstimmung beim Laden eines Moduls:
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 unterKBUILD_SYMTYPES
in Kleaf.Erstellen Sie für Android 13 und niedriger den GKI-Kernel und den Gerätekernel, indem Sie dem Befehl zum Erstellen des Kernels
KBUILD_SYMTYPES=1
voranstellen, 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 FlagKBUILD_SYMTYPES=1
bereits implizit gesetzt.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);
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:Das Format der
.c
-Datei besteht aus einer (potenziell sehr langen) Zeile pro Symbol.[s|u|e|etc]#
am Anfang der Zeile bedeutet, dass das Symbol den Datentyp[struct|union|enum|etc]
hat. 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 * )
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 .symtypes
-Datei eines der Kernel enthält UNKNOWN
als Symbol, während die .symtypes
-Datei des anderen Kernels eine erweiterte Ansicht des Symbols oder Datentyps enthält.
Wenn Sie beispielsweise die folgende Zeile in die Datei include/linux/device.h
in Ihrem Kernel aufnehmen, führt dies zu CRC-Abweichungen, unter anderem 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
hat und der GKI-Kernel die erweiterte Ansicht des Symbols enthält (sehr unwahrscheinlich), führen Sie einen Zusammenschluss des neuesten Android Common Kernel mit Ihrem Kernel durch, damit Sie die neueste GKI-Kernelbasis verwenden.
In den meisten Fällen hat der GKI-Kernel den Wert UNKNOWN
. Ihr Kernel enthält jedoch die internen Details des Symbols, da Änderungen an Ihrem Kernel vorgenommen wurden. 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:
Öffnen Sie die Headerdatei, in der das Symbol oder der Datentyp mit dieser Abweichung definiert ist. Ändern Sie beispielsweise
include/linux/fwnode.h
instruct fwnode_handle
.Fügen Sie oben in der Headerdatei den folgenden Code ein:
#ifdef CRC_CATCH #error "Included from here" #endif
Fügen Sie in der Datei
.c
des Moduls mit einer CRC-Abweichung als erste Zeile vor jeder#include
-Zeile Folgendes ein.#define CRC_CATCH 1
Kompilieren Sie das 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"
Einer der Glieder in dieser
#include
-Kette ist auf eine Änderung in Ihrem Kernel zurückzuführen, die im GKI-Kernel fehlt.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 Datentypänderungen
Wenn die CRC-Nichtübereinstimmung für ein Symbol oder einen Datentyp nicht auf eine Sichtbarkeitsunterschiede zurückzuführen ist, liegt dies an tatsächlichen Änderungen (Ergänzungen, Entfernungen oder Änderungen) des Datentyps 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:
Die Definition des Symbols findest du im Quellcode (normalerweise in
.h
-Dateien).- 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
- Bei gelöschten Symbolen (wenn ein Symbol in einem Baum gelöscht wurde und Sie es auch im anderen Baum löschen möchten) müssen Sie die Änderung finden, durch die die Linie gelöscht wurde. Führen Sie den folgenden Befehl in der Baumstruktur aus, in der die Zeile gelöscht wurde:
git log -S "copy paste of deleted line/word" -- <file where it was deleted>
Sehen Sie sich die zurückgegebene Liste der Commits an, um die Änderung oder das Löschen zu finden. Der erste Commit ist wahrscheinlich der, den Sie suchen. Wenn nicht, gehen Sie die Liste durch, bis Sie den Commit finden.
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.