Monitorowanie interfejsu ABI jądra Androida

Możesz użyć narzędzi do monitorowania interfejsu binarnego aplikacji (ABI), które są dostępne Androida 11 lub nowszego, aby ustabilizować system w jądrze. interfejs ABI jąder Androida. 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 który przedstawia widok, nazywany jest interfejsem modułu jądra. (KMI). Za pomocą tych narzędzi możesz śledzić i ograniczać zmiany w KMI.

Narzędzie do monitorowania ABI to: opracowane w AOSP i zastosowania STG (lub libabigail w Androida 13 i starszych wersji), aby wygenerować i porównać reprezentacji.

Na tej stronie opisujemy narzędzie, czyli proces gromadzenia i analizowania interfejsu ABI. oraz stosowanie takich reprezentacji w celu zapewnienia stabilności i interfejs ABI działający 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ć:

  1. Utwórz jądro i jego reprezentację ABI.
  2. Przeanalizuj różnice w interfejsie ABI między kompilacją a plikiem referencyjnym.
  3. Zaktualizuj reprezentację interfejsu ABI (w razie potrzeby).
  4. Praca z listami symboli.

Poniższe instrukcje sprawdzają się w przypadku jądro, które możesz skompilować obsługiwane narzędzie (np. gotowy łańcuch narzędzi Clang). repo manifests są dostępne we wszystkich gałęziach jądra systemu Android oraz działających na konkretnych urządzeniach, gwarantują one użycie właściwego łańcucha narzędzi aby utworzyć dystrybucję jądra do analizy.

Listy symboli

KMI nie zawiera wszystkich symboli w jądrze,a nawet wszystkich z ponad 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 jedna jądra systemu. Suma wszystkich symboli we wszystkich plikach z listą symboli określa zestaw symboli KMI utrzymywany jako stabilny. Przykładowy plik z listą symboli to Abi_gki_aarch64_db845c deklaruje symbole wymagane dla argumentu 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 nie ma potrzebnych symboli. Po udostępnieniu nowych interfejsów są częścią opisu KMI i są utrzymywane na stabilnym poziomie i nie można ich usuwać z listy symboli ani modyfikować po zablokowany.

Każda gałąź jądra systemu KMI Androida Common jądra (ACK) ma własny zestaw symboli list. Nie podjęto próby zapewnienia stabilności ABI między różnymi jądrami KMI. gałęzie. Na przykład wskaźnik KMI dla lokalizacji android12-5.10 jest całkowicie niezależny od: wskaźnik KMI dla firmy android13-5.10.

Narzędzia ABI wykorzystują listy symboli KMI do ograniczenia, które interfejsy muszą być monitorowane i stabilności. główna lista symboli zawiera symbole wymagane przez moduły jądra GKI. Dostawcy będzie przesyłać i aktualizować dodatkowe listy symboli, aby a interfejsy, na których bazują, zachowują zgodność z interfejsem 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 mają być wymagane w przypadku danego dostawcy lub urządzenia. Ich kompletna lista uwzględnia wszystkie Pliki z listą symboli KMI. Narzędzia ABI określają szczegóły każdego symbolu, w tym podpis funkcji i zagnieżdżone struktury danych.

Gdy KMI jest zablokowany, nie można wprowadzać żadnych zmian w istniejących interfejsach KMI. są stabilne. Dostawcy mogą jednak w dowolnym momencie dodawać symbole do KMI O ile dodatki nie wpływają na stabilność interfejsu ABI. Nowo dodana utrzymują się jak najbardziej stabilne po umieszczeniu na liście symboli KMI. Symbolów nie należy usuwać z listy jądra, jeśli nie można tego potwierdzić że żadne urządzenie jeszcze nie zostało dostarczone 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

Symbole KMI i powiązane z nimi struktury pozostają stabilne (tzn. zmian powodujących uszkodzenie stabilnych interfejsów w jądrze z zablokowanym KMI nie można jądro GKI pozostaje otwarte dla rozszerzeń, dzięki czemu urządzenia pod koniec roku, nie muszą definiować wszystkich zależności, zablokowany. Aby rozszerzyć wskaźnik KMI, można dodać do KMI nowe symbole dla nowych lub z wyeksportowanych funkcji jądra, nawet jeśli wskaźnik KMI jest zablokowany. Nowe jądro poprawki mogą być też akceptowane, jeśli nie wpływają negatywnie na wskaźnik KMI.

Awarie KMI

Jądro ma źródła i na ich podstawie są tworzone pliki binarne. Gałęzie jądra monitorowane przez ABI zawierają reprezentację bieżącego interfejsu GKI przez interfejs ABI ABI (w postaci pliku .stg). Po plikach binarnych (vmlinux, Image i modułów GKI), reprezentację ABI można wyodrębnić z pliki binarne. Wszelkie zmiany wprowadzone w pliku źródłowym jądra mogą mieć wpływ na pliki binarne i ma również wpływ 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ą.

Obsługa awarii 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 interfejs ABI z zastosowaną poprawką, narzędzie zakończy działanie za pomocą niezerowy kod błędu i zgłoszona różnica w interfejsie ABI podobna 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 interfejsie ABI wykryte podczas kompilacji

Najczęstszą przyczyną błędów jest używanie przez kierowcę nowego symbolu z jądra systemu, którego nie ma na żadnej liście 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 te zmiany powodują dodanie nową funkcję przyrostowej szybkości aktualizacji w gałęzi android-12-5.10, obejmuje aktualizację listy symboli i reprezentacji interfejsu ABI XML.

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 potwierdzeniu potwierdzenia (zobacz Zaktualizuj reprezentację interfejsu ABI). Przykład: aktualizacji kodu XML ABI i listy symboli w pliku ACK, zapoznaj się z artykułem ACK aosp/1367601.

Napraw błędy ABI jądra

Możesz poradzić sobie z awariami interfejsu ABI jądra przez zrefaktoryzowanie kodu, aby nie zmieniał ABI lub aktualizowanie reprezentacji interfejsu ABI. Użyj następujących aby wybrać najlepsze podejście w danej sytuacji.

Schemat blokowy awarii ABI

Rysunek 1. Rozwiązywanie problemów z interfejsem ABI

Refaktoryzacja kodu w celu uniknięcia zmian w interfejsie ABI

Postaraj się unikać modyfikowania istniejącego interfejsu ABI. W wielu przypadkach zrefaktoryzować kod, aby usunąć zmiany, które wpływają na interfejs ABI.

  • Zmiany w polu struktury refaktoryzacyjnej. Jeśli zmiana modyfikuje interfejs ABI na potrzeby debugowania , dodaj #ifdef wokół pól (w elementach struct i źródło plików referencyjnych) i upewnij się, że port CONFIG używany w obiekcie #ifdef jest wyłączony dla defconfig produkcji i gki_defconfig. Oto przykład, można dodać do struktury bez naruszania interfejsu ABI. Zapoznaj się z tym artykułem patchset.

  • Funkcje refaktoryzacyjne pozwalające nie wprowadzać zmian w podstawowym jądrze. Jeśli nowe funkcje wymagają należy dodać do potwierdzenia w celu obsługi modułów partnerów, spróbuj zrefaktoryzować interfejs ABI. tej zmiany, by uniknąć modyfikowania interfejsu ABI jądra. Na przykład za pomocą funkcji interfejsu ABI jądra, aby dodać więcej możliwości bez zmiany odniesienie do interfejsu ABI jądra aosp/1312213.

Naprawianie uszkodzonego interfejsu ABI na Androidzie Gerrit

Jeśli nie celowo naruszyłeś interfejs ABI jądra, musisz to zbadać, na podstawie wskazówek dostarczonych przez narzędzia 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 wykrytych przez narzędzie.

Wyniki ABI możesz odtworzyć lokalnie: zobacz Utwórz jądro i jego reprezentację ABI.

Informacje o etykietach 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 stabilną ABI w niezgodny sposób. W trakcie tego procesu AbiAnalyzer szuka Raport ABI utworzony podczas kompilacji (rozszerzona kompilacja, która wykonuje a potem kilka kroków wyodrębniania i porównania za pomocą interfejsu 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.

Aktualizowanie interfejsu ABI jądra

Jeśli modyfikacja interfejsu ABI jest nieunikniona, należy wprowadzić zmiany w kodzie, reprezentację ABI i listę symboli do potwierdzenia. Aby uzyskać dostęp do Lint usuń wartość -1, nie naruszając zgodności z GKI. Wykonaj te czynności:

  1. Prześlij zmiany w kodzie do potwierdzenia.

  2. Poczekaj na otrzymanie weryfikacji kodu +2 dla zestawu poprawek.

  3. Zaktualizuj referencyjną reprezentację ABI.

  4. Połącz zmiany w kodzie i aktualizację ABI.

.

Prześlij zmiany kodu ABI do potwierdzenia

Aktualizacja interfejsu ACK ABI zależy od typu wprowadzanej zmiany.

  • Jeśli zmiana interfejsu ABI jest powiązana z funkcją, która wpływa na testy CTS lub VTS, można zwykle wybierać jako potwierdzenie na potwierdzenie. Na przykład:

  • 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:

  • Jeśli zmiana w interfejsie ABI wprowadza nową funkcję, której nie trzeba uwzględniać w możesz użyć kodu potwierdzenia, tak jak to opisano w w następnej sekcji.

Użyj wycinków z kodem ACK

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 szczegółowych informacji wycinków i częściowych wycinków wiśni w ACK dla GKI.

  • Odizolowany fragment kodu (aosp/1284493). Możliwości w potwierdzeniu nie są konieczne, ale muszą być obecne symbole zatwierdź, aby moduły mogły używać tych symboli.

  • Symbol zastępczy modułu dostawcy (Aosp/1288860).

  • Wybór funkcji śledzenia zdarzeń mm na potrzeby poszczególnych procesów (aosp/1288454). Oryginalna poprawka została wybrana jako ACK, a następnie przycięta, aby zawierała niezbędne zmiany w celu rozwiązania różnic w interfejsach ABI w tych interfejsach: task_struct i mm_event_count Ta poprawka aktualizuje też enum mm_event_type o z ostatnich 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ązano różnice w interfejsach ABI między jądrem partnera a potwierdzeniem.

    • 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 zmiana interfejsu ABI (aosp/1344321). Ta poprawka dodała niezbędne zmiany struct dla interfejsu ABI i zapewniła, że dodatkowe pola nie spowodowały różnicy funkcjonalnej, umożliwiając partnerom do włączenia interfejsu CONFIG_NL80211_TESTMODE w jedna produkcyjne zachowania 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 moduł wymaga niewyeksportowany symbol jest odrzucany. To ograniczenie jest egzekwowane w czasie kompilacji brakujące wpisy są oznaczane.

Do celów programistycznych możesz użyć kompilacji jądra GKI, która nie zawiera – możesz użyć wszystkich zwykle eksportowanych symboli). Aby znaleźć: tych kompilacji, szukaj kompilacji kernel_debug_aarch64 ci.android.com

Wymuszanie KMI za pomocą obsługi wersji modułów

Jądro obrazu jądra (GKI) używają obsługi wersji modułu (CONFIG_MODVERSIONS) jako dodatkowego środka egzekwowania zgodności z KMI na stronie w środowisku wykonawczym. Obsługa wersji modułu może powodować niezgodność z cyklicznym sprawdzaniem nadmiarowości (CRC) błędów w czasie wczytywania modułu, jeśli oczekiwana wartość KMI modułu nie jest zgodna 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 ''

Zastosowania obsługi wersji modułów

Obsługa wersji modułu jest przydatna z tych powodów:

  • Obsługa wersji modułu wykrywa zmiany w widoczności struktury danych. Jeżeli moduły i nieprzezroczystych struktur danych, czyli struktur danych, które nie są częścią KMI, po kolejnych zmianach w strukturze łamią zasady.

    Weźmy na przykład fwnode polu w struct device. To pole MUSI być nieprzezroczyste dla modułów, aby nie można było w nich wprowadzać zmian device->fw_node lub oszacować jego rozmiar.

    Jeśli jednak moduł zawiera tag <linux/fwnode.h> (bezpośrednio lub pośrednio): pole fwnode w struct device nie jest już dla niego nieprzezroczyste. moduł może następnie wprowadzać zmiany w elemencie device->fwnode->dev lub device->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 (dane typu fwnode), moduł nie będzie już działać z nowym jądrem. Co więcej, moduł stgdiff nie pokaże żadnych różnic, ponieważ moduł ulega awarii KMI przez bezpośrednie manipulowanie wewnętrznymi strukturami danych w sposób można przechwycić tylko na podstawie reprezentacji binarnej.

  • Bieżący moduł zostanie uznany za niezgodny z KMI, gdy zostanie wczytany później w ramach nowego, niezgodnego jądra systemu. Obsługa wersji modułu dodaje kontrolę środowiska wykonawczego do uniknąć przypadkowego wczytania modułu, który jest niezgodny z jądrem KMI. Ta kontrola zapobiega trudnym do debugowania problemów w czasie działania i awariom jądra, które mogą wynika z niewykrytej niezgodności w KMI.

Włączenie obsługi wersji modułów zapobiega tym problemom.

Sprawdź 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.

Dodatkowo pełna kompilacja jądra z włączoną obsługą CONFIG_MODVERSIONS generuje Module.symvers w ramach normalnego procesu kompilacji. Ten plik zawiera jedną dla każdego symbolu wyeksportowanego 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 między kompilacją GKI a kompilacją aby sprawdzić różnice w kodach CRC w symbolach eksportowanych przez vmlinux. Jeśli 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 niezgodności CRC podczas wczytywania modułu:

  1. Utwórz jądro GKI i jądro urządzenia za pomocą --kbuild_symtypes jak w tym poleceniu:

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

    To polecenie generuje plik .symtypes dla każdego pliku .o. Zobacz KBUILD_SYMTYPES w Kleaf .

    W przypadku Androida 13 lub starszego utwórz jądro GKI. i jądro urządzenia, dodając na początku polecenia KBUILD_SYMTYPES=1 użyj do skompilowania jądra, jak pokazano w tym poleceniu:

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

    Jeśli używasz build_abi.sh,, flaga KBUILD_SYMTYPES=1 jest domyślnie ustawiona już teraz.

  2. 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);
    
  3. Plikowi .c ma odpowiedni plik .symtypes w GKI, a artefaktów 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
    

    Plik .c ma te cechy:

    • Format pliku .c to jeden (potencjalnie bardzo długi) wiersz na symbol.

    • [s|u|e|etc]# na początku wiersza oznacza, że symbol jest typu danych. [struct|union|enum|etc] Na przykład:

      t#bool typedef _Bool bool
      
    • Brak prefiksu # na początku wiersza oznacza, że symbol jest funkcją. Na przykład:

      find_module s#module * find_module ( const char * )
      
  4. 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 pozostawia symbol lub typ danych nieprzezroczyste dla modułów, a drugie jest nieprzezroczyste. jądro nie działa, ta różnica pojawia się między plikami .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 jądro ma wartość UNKNOWN, a jądro GKI ma widok rozwinięty (to bardzo mało prawdopodobne), a następnie scal najnowszy system Android Common Jądro z jądra systemu, aby korzystać z najnowszej wersji bazy 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.

Zazwyczaj rozwiązaniem problemu jest ukrywanie nowego elementu #include w interfejsie genksyms.

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

W przeciwnym razie wykonaj te czynności, aby zidentyfikować element #include powodujący różnicę. kroki:

  1. Otwórz plik nagłówka, który definiuje symbol lub typ danych z tym symbolem różnicy. Na przykład edytuj pole include/linux/fwnode.h dla atrybutu struct fwnode_handle

  2. Na początku pliku nagłówka dodaj następujący kod:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. 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
    
  4. Skompiluj moduł. Powstały błąd w czasie kompilacji pokazuje łańcuch pliku 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"
    

    Jedno z ogniw w tym łańcuchu połączeń #include jest spowodowane zmianą wprowadzoną w Google, którego brakuje w jądrze GKI.

  5. Zidentyfikuj zmianę, cofnij ją w jądrze lub prześlij je do ACK i połącz je ze swoim kontem.

Przypadek 2: różnice wynikające ze zmian 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 zidentyfikować zmieniony typ, wykonaj te czynności:

  1. 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>
    
  2. Przejrzyj zwrócona listę zatwierdzeń, aby znaleźć zmianę lub usunięcie. pierwsze zatwierdzenie jest prawdopodobnie tym, którego szukasz. Jeśli nie, kliknij przejrzeć listę, aż znajdziesz zatwierdzenie.

  3. Po zidentyfikowaniu zmiany przywróć ją w jądrze lub prześlij do ACK i pobierz scalone.