Aby ustabilizować interfejs ABI wewnątrz jądra w jądrach Androida, możesz użyć narzędzia do monitorowania interfejsu binarnego aplikacji (ABI), dostępnego w Androidzie 11 i nowszych. Narzędzie zbiera i porównuje reprezentacje ABI
z istniejących plików binarnych jądra (vmlinux
+ moduły GKI). Te interfejsy ABI
reprezentacje to pliki .stg
i listy symboli. Interfejs włączony
z którego przedstawiany jest widok, nazywany jest interfejsem modułu jądra.
(KMI). Za pomocą tych narzędzi możesz śledzić i ograniczać zmiany w KMI.
Narzędzia do monitorowania ABI są opracowywane w AOSP i korzystają z STG (lub libabigail
w Androidzie 13 i starszych), aby generować i porównywać reprezentacje.
Na tej stronie opisujemy narzędzia, proces zbierania i analizowania reprezentacji ABI oraz używanie tych reprezentacji do zapewnienia stabilności interfejsu ABI w jądrze. Ta strona zawiera również informacje na temat wprowadzania zmian do jąder Androida.
Proces
Analiza interfejsu ABI jądra składa się z wielu kroków, z których większość z nich można zautomatyzować:
- Utwórz jądro i jego reprezentacja ABI.
- Przeanalizuj różnice w interfejsie ABI między kompilacją a plikiem referencyjnym.
- Zaktualizuj reprezentację ABI (jeśli to konieczne).
- Praca z listami symboli.
Podane niżej instrukcje dotyczą dowolnego jądra, które możesz skompilować za pomocą obsługiwanego zestawu narzędzi (np. wstępnie skompilowanego zestawu narzędzi Clang). repo manifests
są dostępne we wszystkich gałęziach jądra systemu Android oraz
działających na różnych urządzeniach, gwarantują one użycie
właściwego łańcucha narzędzi
aby utworzyć dystrybucję jądra do analizy.
Listy symboli
KMI nie obejmuje wszystkich symboli w jądrze ani nawet wszystkich 30 tys. wyeksportowanych symboli. Symbole, których mogą używać moduły dostawców, to jawnie wymienione w zestawie plików z listą symboli udostępnianych publicznie w katalogu głównym z jednego jądra systemu. Suma wszystkich symboli we wszystkich plikach z listą symboli definiuje zestaw symboli KMI utrzymywany na stabilnym poziomie. Przykładowy plik z listą symboli to abi_gki_aarch64_db845c, który deklaruje symbole wymagane dla DragonBoard 845c.
Tylko symbole wymienione na liście symboli i powiązane z nimi struktury są uznawane za część KMI. Możesz opublikować zmiany w swoich jeśli brakuje potrzebnych symboli. Gdy nowe interfejsy zostaną dodane do listy symboli i staną się częścią opisu KMI, będą traktowane jako stabilne. Nie można ich usuwać z listy symboli ani modyfikować po zamrożeniu gałęzi.
Każda gałąź jądra systemu KMI Androida Common jądra (ACK) ma własny zestaw symboli
list. Nie podejmuje się prób zapewnienia stabilności ABI między różnymi gałęziami jądra KMI. Na przykład KMI dla android12-5.10
jest całkowicie niezależny od KMI dla android13-5.10
.
Narzędzia ABI wykorzystują listy symboli KMI do ograniczenia, które interfejsy muszą być monitorowane
i stabilności. Lista głównych symboli zawiera symbole wymagane przez moduły jądra GKI. Dostawcy powinni przesyłać i aktualizować dodatkowe listy symboli, aby mieć pewność, że interfejsy, których używają, zachowują zgodność z ABI. Aby na przykład wyświetlić listę
list symboli dla android13-5.15
, patrz
https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android
Lista symboli zawiera symbole, które są potrzebne w przypadku konkretnego dostawcy lub urządzenia. Pełna lista używana przez narzędzia jest zbiorem wszystkich plików listy symboli KMI. Narzędzia ABI określają szczegóły każdego symbolu, w tym sygnaturę funkcji i zagnieżdżone struktury danych.
Gdy interfejs KMI jest zamrożony, nie można wprowadzać żadnych zmian w dotychczasowych interfejsach KMI, ponieważ są one stabilne. Dostawcy mogą jednak dodawać symbole do KMI w dowolnym momencie, o ile nie wpłynie to na stabilność istniejącego ABI. Nowo dodane symbole są utrzymywane w stanie stabilnym od momentu, gdy są one wymienione na liście symboli KMI. Symboli nie należy usuwać z listy jądra, chyba że można potwierdzić, że żadne urządzenie nigdy nie było dostarczane z zależnością od tego symbolu.
Możesz wygenerować listę symboli KMI dla danego urządzenia, postępując zgodnie z instrukcjami z Jak korzystać z list symboli. Wielu partnerów przesyła po 1 liście symboli na każde potwierdzenie, ale nie jest to absolutnie wymagane. Jeśli ułatwi to konserwację, możesz przesłać kilka list symboli.
Rozszerzenie KMI
Chociaż symbole KMI i powiązane z nimi struktury są utrzymywane jako stabilne (co oznacza, że zmiany, które powodują niestabilność interfejsów w jądrze z zamrożonym KMI, nie mogą być akceptowane), jądro GKI pozostaje otwarte na rozszerzenia, aby urządzenia wysyłane w późniejszej części roku nie musiały definiować wszystkich swoich zależności przed zamrożeniem KMI. Aby rozszerzyć KMI, możesz dodać do niego nowe symbole dla nowych lub istniejących wyeksportowanych funkcji jądra, nawet jeśli KMI jest zamrożony. Nowe jądro poprawki mogą być też akceptowane, jeśli nie wpływają negatywnie na wskaźnik KMI.
Informacje o awariach KMI
Kernel ma źródła, na podstawie których są tworzone pliki binarne.
Gałęzie jądra monitorowane pod kątem ABI zawierają reprezentację ABI bieżącego ABI GKI (w postaci pliku .stg
). Po plikach binarnych (vmlinux
, Image
i
dowolnych modułów GKI), reprezentację ABI można wyodrębnić z
pliki binarne. Każda zmiana wprowadzona w pliku źródłowym jądra może wpłynąć na pliki binarne, a w efekcie także na wyodrębnione .stg
. Analizator AbiAnalyzer
porównuje
zatwierdzony plik .stg
z tym wyodrębnionym z artefaktów kompilacji i ustawia
Etykieta Lint-1 dotycząca zmiany w Gerrit, jeśli znajdzie różnicę semantyczną.
Rozwiązywanie problemów z interfejsem ABI
Przykład: ta poprawka wprowadza bardzo oczywisty błąd interfejsu 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.
Gdy uruchomisz kompilację ABI z zaimplementowaną łatką, narzędzie zakończy działanie z kodem błędu niezerowego i zgłosi różnicę w ABI podobną do tej:
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
różnice w ABI wykryte w momencie kompilacji,
Najczęstszą przyczyną błędów jest użycie przez sterownik nowego symbolu z jądra, którego nie ma na żadnej z list symboli.
Jeśli symbolu nie ma na liście symboli (android/abi_gki_aarch64
),
musisz najpierw sprawdzić, czy dane są eksportowane
EXPORT_SYMBOL_GPL(symbol_name)
, a następnie zaktualizuj
Reprezentacja ABI XML i lista symboli. Na przykład poniższe zmiany wprowadzają do gałęzi android-12-5.10
nową funkcję przyrostowego FS, która obejmuje zaktualizowanie listy symboli i reprezentacji XML ABI.
- Przykład zmiany funkcji znajduje się w aosp/1345659.
- Przykład listy symboli jest dostępny aosp/1346742.
- Przykład zmiany ABI XML jest w aosp/1349377.
Jeśli symbol został wyeksportowany (przez Ciebie lub wcześniej), ale nie został wyeksportowany z innego sterownika, może wystąpić błąd kompilacji podobny do poniższego.
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
Aby rozwiązać ten problem, zaktualizuj listę symboli KMI zarówno w jądrze, jak i w ACK (patrz Aktualizowanie reprezentacji ABI). Przykład aktualizacji pliku XML ABI i listy symboli w pliku ACK znajdziesz w problemie aosp/1367601.
Napraw błędy ABI jądra
Możesz rozwiązać problem z naruszeniem ABI jądra, przekształcając kod, aby nie zmieniać ABI lub zaktualizować reprezentację ABI. Aby określić, która metoda jest najlepsza w Twojej sytuacji, skorzystaj z tabeli poniżej.
Rysunek 1. Rozwiązanie problemu z naruszeniem ABI
Refaktoryzacja kodu w celu uniknięcia zmian w interfejsie ABI
Dokładaj wszelkich starań, aby nie modyfikować istniejącego ABI. W wielu przypadkach zrefaktoryzować kod, aby usunąć zmiany, które wpływają na interfejs ABI.
Refaktoryzacja zmian pól struktury. Jeśli zmiana modyfikuje ABI funkcji debugowania, dodaj
#ifdef
wokół pól (w strukturach i odniesieniach do źródła) i upewnij się, żeCONFIG
używany w#ifdef
jest wyłączony w defconfigie produkcyjnym igki_defconfig
. Przykład dodawania konfiguracji debugowania do struktury bez naruszania ABI znajdziesz w tym zestawie poprawek.Refaktoryzacja funkcji, aby nie zmieniać jądra jądra. Jeśli do ACK trzeba dodać nowe funkcje, aby obsługiwać moduły partnera, spróbuj przerobić ABI w ramach zmiany, aby uniknąć modyfikowania ABI jądra. Przykład użycia istniejącego interfejsu ABI jądra w celu dodania dodatkowych funkcji bez zmiany interfejsu ABI jądra: aosp/1312213.
Naprawianie nieprawidłowego ABI w Gerrite na Androida
Jeśli nie doszło do celowego naruszenia ABI jądra, musisz zbadać problem, korzystając z wskazówek podanych przez narzędzie do monitorowania ABI. Najczęstsze przyczyny awarii to zmienione struktury danych i powiązany symbol CRC zmian opcji konfiguracji lub zmian opcji konfiguracji, które prowadzą do wystąpienia któregokolwiek z wyżej wymienionych problemów. Zacznij od rozwiązania problemów znalezionych przez narzędzie.
Wyniki ABI możesz odtworzyć lokalnie: zobacz Utwórz jądro i jego reprezentację ABI.
Etykiety Lint-1
Jeśli prześlesz zmiany do gałęzi zawierającej zablokowany lub sfinalizowany wskaźnik KMI,
zmiany muszą przejść przez AbiAnalyzer
, aby zapewnić, że zmiany nie wpłyną na wersję stabilną
ABI w niezgodny sposób. Podczas tego procesu AbiAnalyzer
szuka raportu ABI utworzonego podczas kompilacji (rozszerzona kompilacja, która wykonuje normalną kompilację, a następnie niektóre kroki ekstrakcji i porównywania ABI).
Jeśli AbiAnalyzer
znajdzie niepusty raport, ustawi etykietę Lint-1 i
możliwość przesłania zmiany jest blokowana do czasu rozwiązania problemu; dopóki zbiór poprawek nie otrzyma
Etykieta Lint + 1.
Aktualizacja ABI jądra
Jeśli modyfikacja ABI jest nieunikniona, musisz zastosować zmiany kodu, reprezentację ABI i listę symboli w ACK. Aby uzyskać dostęp do Lint usuń wartość -1, nie naruszając zgodności z GKI. Wykonaj te czynności:
Poczekaj na otrzymanie weryfikacji kodu +2 dla zestawu poprawek.
Połącz zmiany w kodzie i aktualizację ABI.
Prześlij zmiany kodu ABI do potwierdzenia
Aktualizacja ABI ACK zależy od typu wprowadzanej zmiany.
Jeśli zmiana ABI jest związana z funkcją, która wpływa na testy CTS lub VTS, można ją zwykle zastosować do ACK w postaci dosłownej. Na przykład:
- Aby dźwięk działał, musisz mieć zainstalowaną wersję aosp/1289677.
- Aosp/1295945 USB jest niezbędne do działania USB.
Jeśli zmiana interfejsu ABI dotyczy funkcji, którą można udostępnić do potwierdzenia, można wybrać jako potwierdzenie w niezmienionej formie. Na przykład te zmiany nie są wymagane do testów CTS ani VTS, ale można je udostępnić ACK:
- Aosp/1250412 oznacza zmianę obiektu termicznego.
- aosp/1288857
to zmiana
EXPORT_SYMBOL_GPL
.
Jeśli zmiana ABI wprowadza nową funkcję, która nie musi być uwzględniona w ACK, możesz wprowadzić symbole do ACK za pomocą zastępnika zgodnie z opisem w następującej sekcji.
Używanie pustych odpowiedzi na potwierdzenie
Fragmenty muszą być konieczne tylko po wprowadzeniu zmian w rdzeniu jądra, które nie przynoszą korzyści potwierdzenia, na przykład o wydajności i zasilaniu. Poniżej znajdziesz przykłady stubów i częściowych elementów w ACK dla GKI.
Odizolowany fragment kodu (aosp/1284493). Funkcje w ACK nie są wymagane, ale symbole muszą być obecne w ACK, aby moduły mogły ich używać.
Symbol zastępczy dla modułu dostawcy (aosp/1288860).
Funkcja śledzenia zdarzeń
mm
(aosp/1288454) korzystająca z funkcji selektywnego korzystania z funkcji śledzenia zdarzeń (tylko ABI). Pierwotny pakiet poprawek został wybrany do zaakceptowania, a potem przycięty tak, aby zawierał tylko zmiany niezbędne do rozwiązania różnic w ABI w przypadkutask_struct
imm_event_count
. Ta poprawka aktualizuje też enumeracjęmm_event_type
, aby zawierała ostatecznych członków.Częściowy wybór zmian w interfejsie ABI struktury termicznej, które wymagały więcej niż tylko dodając nowe pola ABI.
Poprawka aosp/1255544 rozwiązała różnice w ABI między jądrem partnera a ACK.
Poprawka Aosp/1291018 naprawiliśmy problemy funkcjonalne występujące podczas testowania GKI w poprzedniej poprawce. Poprawka obejmuje zainicjowanie struktury parametru czujnika w celu rejestracji do jednego czujnika.
CONFIG_NL80211_TESTMODE
Zmiany ABI (aosp/1344321). Ta poprawka wprowadziła niezbędne zmiany struktury dla ABI i zadbała o to, aby dodatkowe pola nie powodowały różnic w funkcjonalności, co umożliwiło partnerom uwzględnienieCONFIG_NL80211_TESTMODE
w ich produkcyjnych jądrach i zachowanie zgodności z GKI.
Egzekwuj KMI w czasie działania
Jądro GKI używają opcji konfiguracji TRIM_UNUSED_KSYMS=y
i UNUSED_KSYMS_WHITELIST=<union
of all symbol lists>
, które ograniczają eksportowanie symboli
(np. symboli eksportowanych przy użyciu EXPORT_SYMBOL_GPL()
) do tych, które zostały wymienione na
listę symboli. Pozostałe symbole nie są eksportowane, a wczytywanie modułu wymagającego niewyeksportowanego symbolu jest zabronione. To ograniczenie jest egzekwowane w czasie kompilacji
brakujące wpisy są oznaczane.
Na potrzeby programowania możesz użyć wersji jądra GKI, która nie obejmuje przycinania symboli (co oznacza, że można używać wszystkich symboli wyeksportowanych w standardowy sposób). Aby znaleźć te wersje, poszukaj wersji kernel_debug_aarch64
na stronie ci.android.com.
Wymuszanie KMI za pomocą obsługi wersji modułów
Kernele z obrazu Generic Kernel Image (GKI) korzystają z wersji modułów (CONFIG_MODVERSIONS
) jako dodatkowego sposobu egzekwowania zgodności z KMI w czasie wykonywania. Wersja modułu może powodować błędy niezgodności CRC podczas wczytywania modułu, jeśli oczekiwany KMI modułu nie jest zgodny z vmlinux
KMI. Na przykład ten problem to typowa awaria, która występuje w
czas wczytywania modułu z powodu niezgodności CRC dla symbolu 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 ''
Zastosowanie obsługi wersji modułów
Wersje modułów są przydatne z tych powodów:
Wersje modułów rejestrują zmiany w widoczności struktury danych. Jeśli moduły zmieniają nieprzezroczyste struktury danych, czyli struktury danych, które nie są częścią interfejsu KMI, przestają działać po wprowadzeniu zmian w strukturze.
Weź pod uwagę na przykład pole
fwnode
w plikustruct device
. To pole MUSI być nieprzezroczyste dla modułów, aby nie można było w nich wprowadzać zmiandevice->fw_node
lub oszacować jego rozmiar.Jeśli jednak moduł zawiera tag
<linux/fwnode.h>
(bezpośrednio lub pośrednio): polefwnode
wstruct device
nie jest już dla niego nieprzezroczyste. moduł może następnie wprowadzać zmiany w elemenciedevice->fwnode->dev
lubdevice->fwnode->ops
Ten scenariusz jest problematyczny z kilku powodów, stwierdza się w następujący sposób:Może złamać założenia, na które opiera się podstawowy kod jądra, struktury danych.
Jeśli przyszła aktualizacja jądra zmieni
struct fwnode_handle
(typ danychfwnode
), moduł przestanie działać z nowym jądrem. Ponadtostgdiff
nie będzie wykazywać żadnych różnic, ponieważ moduł narusza KMI, bezpośrednio manipulując wewnętrznymi strukturami danych w sposób, którego nie można uchwycić, tylko przeglądając reprezentacje binarne.
Bieżący moduł zostanie uznany za niezgodny z KMI, gdy zostanie wczytany później w ramach nowego, niezgodnego jądra systemu. Wersja modułu dodaje kontrolę w czasie działania, aby uniknąć przypadkowego załadowania modułu, który nie jest zgodny z jądro KMI. Ten test zapobiega trudnym do debugowania problemom w czasie działania i awariom jądra, które mogą być spowodowane niewykrytą niezgodnością w KMI.
Włączenie obsługi wersji modułów zapobiega tym problemom.
Sprawdzanie niezgodności CRC bez uruchamiania urządzenia
stgdiff
porównuje i zgłasza niezgodności CRC między jądrami i innymi
Różnice w interfejsie ABI.
Ponadto podczas pełnego kompilowania jądra z włączoną opcją CONFIG_MODVERSIONS
generowany jest plik Module.symvers
w ramach normalnego procesu kompilacji. Ten plik zawiera po jednym wierszu na każdy symbol wyeksportowany przez jądro (vmlinux
) i moduły. Każdy
wiersz składa się z wartości CRC, nazwy symbolu, przestrzeni nazw symbolu, znaku vmlinux
lub
nazwy modułu, z którego jest eksportowany symbol, oraz typu eksportu (np.
EXPORT_SYMBOL
w porównaniu z EXPORT_SYMBOL_GPL
).
Możesz porównać pliki Module.symvers
z wersji GKI i swojej wersji, aby sprawdzić, czy w symbolach wyeksportowanych przez vmlinux
występują różnice CRC. Jeśli tam
to różnica wartości CRC w dowolnym symbolu eksportowanym przez vmlinux
oraz, który
jest używany przez jeden z modułów wczytywanych do urządzenia, moduł nie jest
strony.
Jeśli nie masz wszystkich artefaktów kompilacji, ale masz pliki vmlinux
z jądra systemu GKI i jądra, możesz porównywać wartości CRC dla określonego
przez uruchomienie poniższego polecenia w obu jądrach i porównanie
dane wyjściowe:
nm <path to vmlinux>/vmlinux | grep __crc_<symbol name>
Na przykład poniższe polecenie sprawdza wartość CRC dla: module_layout
symbol:
nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout
Rozwiąż problemy z niezgodnością CRC
Aby rozwiązać problem z niezgodnością CRC podczas wczytywania modułu, wykonaj te czynności:
Utwórz jądro GKI i jądro urządzenia, używając opcji
--kbuild_symtypes
, jak pokazano w tym poleceniu:tools/bazel run --kbuild_symtypes //common:kernel_aarch64_dist
To polecenie generuje plik
.symtypes
dla każdego pliku.o
. ZobaczKBUILD_SYMTYPES
w Kleaf .W przypadku Androida 13 i starszych kompiluj jądro GKI oraz jądro urządzenia, dodając do polecenia kompilacji
KBUILD_SYMTYPES=1
, jak w tym przykładzie:KBUILD_SYMTYPES=1 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
Gdy używasz parametru
build_abi.sh,
, flagaKBUILD_SYMTYPES=1
jest już domyślnie ustawiona.Znajdź plik
.c
, w którym eksportowany jest symbol z niezgodnością CRC, używając kodu następujące polecenie:cd common && git grep EXPORT_SYMBOL.*module_layout kernel/module.c:EXPORT_SYMBOL(module_layout);
Plik
.c
ma odpowiadający mu plik.symtypes
w GKI oraz artefakty kompilacji jądra urządzenia. Znajdź plik.c
za pomocą tego polecenia:cd out/$BRANCH/common && ls -1 kernel/module.* kernel/module.o kernel/module.o.symversions kernel/module.symtypes
Poniżej znajdziesz informacje o pliku
.c
:Format pliku
.c
to 1 wiersz (potencjalnie bardzo długi) na symbol.[s|u|e|etc]#
na początku wiersza oznacza, że symbol ma typ danych[struct|union|enum|etc]
. Na przykład:t#bool typedef _Bool bool
Brakujący na początku wiersza prefiks
#
wskazuje, że symbol jest funkcją. Na przykład:find_module s#module * find_module ( const char * )
Porównaj oba pliki i wyeliminuj wszystkie różnice.
Przypadek 1. Różnice wynikające z widoczności typu danych
Jeśli jedno jądro ukrywa symbol lub typ danych przed modułami, a drugie nie, ta różnica pojawi się w plikach .symtypes
tych dwóch jąder. Plik .symtypes
z jednego z jąder zawiera UNKNOWN
dla symbolu, a plik .symtypes
z drugiego jądra ma widok rozwinięty
symbolu lub typu danych.
Na przykład dodanie tego wiersza do
include/linux/device.h
w jądrze powoduje niezgodności CRC. Jedna z tych
jest dla module_layout()
:
#include <linux/fwnode.h>
Porównanie module.symtypes
dla tego symbolu powoduje ujawnienie tych elementów
różnice:
$ 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 ] ; }
...
Jeśli wartość Twojego jądra to UNKNOWN
, a jądro GKI zawiera rozszerzony widok symbolu (bardzo mało prawdopodobne), scal najnowsze jądro Android Common Kernel ze swoim jądrem, aby używać najnowszej wersji jądra GKI.
W większości przypadków jądro GKI ma wartość UNKNOWN
, a jądro ma wartość
z wewnętrznych szczegółów symbolu powodowanych przez zmiany wprowadzone w jądrze. To jest
ponieważ jeden z plików w jądrze dodał element #include
, którego nie ma w
przez jądro GKI.
Często wystarczy ukryć nowy element #include
z elementu genksyms
.
#ifndef __GENKSYMS__
#include <linux/fwnode.h>
#endif
Aby zidentyfikować #include
, który powoduje różnicę, wykonaj te czynności:
Otwórz plik nagłówka, który definiuje symbol lub typ danych z tą różnicą. Zmodyfikuj na przykład kolumnę
include/linux/fwnode.h
w wierszustruct fwnode_handle
.Na początku pliku nagłówka dodaj następujący kod:
#ifdef CRC_CATCH #error "Included from here" #endif
W pliku
.c
modułu, w którym występuje niezgodność CRC, dodaj parametr jako pierwszy wiersz przed dowolnym z wierszy#include
.#define CRC_CATCH 1
Zkompiluj moduł. Wygenerowany błąd w czasie kompilacji zawiera łańcuch plików nagłówka
#include
, który doprowadził do niezgodności CRC. Na przykład: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"
Jeden z linków w tym łańcuchu
#include
jest spowodowany zmianą w jądrze, która nie występuje w jądrze GKI.Zidentyfikuj zmianę, cofnij ją w jądrze lub prześlij je do ACK i połącz je ze swoim kontem.
Przypadek 2. Różnice spowodowane zmianami typu danych
Jeśli niezgodność CRC dla symbolu lub typu danych nie wynika z różnicy w wynika z faktycznych zmian (dodatków, usunięć lub zmian) w typ danych.
Na przykład wprowadzenie poniższej zmiany w jądrze spowoduje wygenerowanie kilku CRC niezgodności, ponieważ ten typ zmiany pośrednio wpływa na wiele symboli:
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);
Jedna niezgodność CRC dotyczy devm_of_platform_populate()
.
Porównując pliki .symtypes
dotyczące tego symbolu, może ono wyglądać tak:
$ 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 * ) ; ...
Aby określić zmieniony typ, wykonaj te czynności:
Znajdź definicję tego symbolu w kodzie źródłowym (zwykle w plikach
.h
).- W przypadku różnic pod względem symboli między jądrem systemu a jądrem GKI znaleźć zatwierdzenie, uruchamiając to polecenie:
git blame
- Usunięte symbole (gdy symbol jest usunięty z drzewa, a ponadto w innym drzewie, musisz znaleźć zmianę, usunął ten wiersz. Użyj poniższego polecenia na drzewie, w którym wiersz usunięto:
git log -S "copy paste of deleted line/word" -- <file where it was deleted>
Przejrzyj zwrócona listę zatwierdzeń, aby znaleźć zmianę lub usunięcie. Pierwszy commit to prawdopodobnie ten, którego szukasz. Jeśli nie, przejrzyj listę, aż znajdziesz odpowiednią wersję.
Po zidentyfikowaniu zmiany cofnij ją w jądrze lub prześlij do ACK i połącz ją z jądrem.