1. add kabi helper macros 2. add kabi tools: kabideps, kabisyms, check-kabi
Li Lingfeng (1): kabi: deduplication friendly structs
Xie XiuQi (5): kabi: add KABI_SIZE_ALIGN_CHECKS for more stringent kabi checks kabi: enables more stringent kabi checks kabi: add script tools to check kabi symbol kabi: add a tool to generate the kabi reference relationship kabi: add kABI reference checking tool
Zheng Zengkai (4): kabi: add kabi helper macros KABI: Add CONFIG_KABI_RESERVE to control KABI padding reserve openeuler_defconfig: Enable CONFIG_KABI_RESERVE for x86 and arm64 kabi: Generalize naming of kabi helper macros
Kconfig | 15 + arch/arm64/configs/openeuler_defconfig | 2 + arch/x86/configs/openeuler_defconfig | 2 + include/linux/kabi.h | 509 +++++++++++++++++++++++++ scripts/check-kabi | 147 +++++++ scripts/kabideps | 161 ++++++++ scripts/kabisyms | 141 +++++++ 7 files changed, 977 insertions(+) create mode 100644 include/linux/kabi.h create mode 100755 scripts/check-kabi create mode 100755 scripts/kabideps create mode 100755 scripts/kabisyms
From: Zheng Zengkai zhengzengkai@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
--------------------------------
We intruduce kabi helper macros which derived from RHEL "include/linux/rh_kabi.h", tried to standardize the kabi work on openEuler.
Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Signed-off-by: Xie XiuQi xiexiuqi@huawei.com Reviewed-by: Cheng Jian cj.chengjian@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- include/linux/kabi.h | 499 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 499 insertions(+) create mode 100644 include/linux/kabi.h
diff --git a/include/linux/kabi.h b/include/linux/kabi.h new file mode 100644 index 000000000000..da5e6d71e66b --- /dev/null +++ b/include/linux/kabi.h @@ -0,0 +1,499 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * kabi.h - openEuler kABI abstraction header + * + * Copyright (c) 2014 Don Zickus + * Copyright (c) 2015-2018 Jiri Benc + * Copyright (c) 2015 Sabrina Dubroca, Hannes Frederic Sowa + * Copyright (c) 2016-2018 Prarit Bhargava + * Copyright (c) 2017 Paolo Abeni, Larry Woodman + * Copyright (c) 2021 Xie XiuQi xiexiuqi@huawei.com + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + * + * These kabi macros hide the changes from the kabi checker and from the + * process that computes the exported symbols' checksums. + * They have 2 variants: one (defined under __GENKSYMS__) used when + * generating the checksums, and the other used when building the kernel's + * binaries. + * + * The use of these macros does not guarantee that the usage and modification + * of code is correct. As with all openEuler only changes, an engineer must + * explain why the use of the macro is valid in the patch containing the + * changes. + * + * The macro helpers are derived from RHEL "include/linux/rh_kabi.h" + * Mostly debrand from RHEL. + */ + +#ifndef _LINUX_KABI_H +#define _LINUX_KABI_H + +#include <linux/compiler.h> +#include <linux/stringify.h> + +/* + * NOTE + * Unless indicated otherwise, don't use ';' after these macros as it + * messes up the kABI checker by changing what the resulting token string + * looks like. Instead let the macros add the ';' so it can be properly + * hidden from the kABI checker (mainly for KABI_EXTEND, but applied to + * most macros for uniformity). + * + * KABI_CONST + * Adds a new const modifier to a function parameter preserving the old + * checksum. + * + * KABI_ADD_MODIFIER + * Adds a new modifier to a function parameter or a typedef, preserving + * the old checksum. Useful e.g. for adding rcu annotations or changing + * int to unsigned. Beware that this may change the semantics; if you're + * sure this is safe, always explain why binary compatibility with 3rd + * party modules is retained. + * + * KABI_DEPRECATE + * Marks the element as deprecated and make it unusable by modules while + * keeping a hole in its place to preserve binary compatibility. + * + * # define KABI_BROKEN_INSERT_ENUM(_new) _new, + * # define KABI_BROKEN_REMOVE_ENUM(_orig) + * KABI_DEPRECATE_FN + * Marks the function pointer as deprecated and make it unusable by modules + * while keeping a hole in its place to preserve binary compatibility. + * + * KABI_EXTEND + * Adds a new field to a struct. This must always be added to the end of + * the struct. Before using this macro, make sure this is actually safe + * to do - there is a number of conditions under which it is *not* safe. + * In particular (but not limited to), this macro cannot be used: + * - if the struct in question is embedded in another struct, or + * - if the struct is allocated by drivers either statically or + * dynamically, or + * - if the struct is allocated together with driver data (an example of + * such behavior is struct net_device or struct request). + * + * KABI_EXTEND_WITH_SIZE + * Adds a new element (usually a struct) to a struct and reserves extra + * space for the new element. The provided 'size' is the total space to + * be added in longs (i.e. it's 8 * 'size' bytes), including the size of + * the added element. It is automatically checked that the new element + * does not overflow the reserved space, now nor in the future. However, + * no attempt is done to check the content of the added element (struct) + * for kABI conformance - kABI checking inside the added element is + * effectively switched off. + * For any struct being added by KABI_EXTEND_WITH_SIZE, it is + * recommended its content to be documented as not covered by kABI + * guarantee. + * + * KABI_FILL_HOLE + * Fills a hole in a struct. + * + * Warning: only use if a hole exists for _all_ arches. Use pahole to verify. + * + * KABI_RENAME + * Renames an element without changing its type. This macro can be used in + * bitfields, for example. + * + * NOTE: does not include the final ';' + * + * KABI_REPLACE + * Replaces the _orig field by the _new field. The size of the occupied + * space is preserved, it's fine if the _new field is smaller than the + * _orig field. If a _new field is larger or has a different alignment, + * compilation will abort. + * + * + * KABI_HIDE_INCLUDE + * Hides the given include file from kABI checksum computations. This is + * used when a newly added #include makes a previously opaque struct + * visible. + * + * Example usage: + * #include KABI_HIDE_INCLUDE(<linux/poll.h>) + * + * KABI_FAKE_INCLUDE + * Pretends inclusion of the given file for kABI checksum computations. + * This is used when upstream removed a particular #include but that made + * some structures opaque that were previously visible and is causing kABI + * checker failures. + * + * Example usage: + * #include KABI_FAKE_INCLUDE(<linux/rhashtable.h>) + * + * KABI_RESERVE + * Adds a reserved field to a struct. This is done prior to kABI freeze + * for structs that cannot be expanded later using KABI_EXTEND (for + * example because they are embedded in another struct or because they are + * allocated by drivers or because they use unusual memory layout). The + * size of the reserved field is 'unsigned long' and is assumed to be + * 8 bytes. + * + * The argument is a number unique for the given struct; usually, multiple + * KABI_RESERVE macros are added to a struct with numbers starting from + * one. + * + * Example usage: + * struct foo { + * int a; + * KABI_RESERVE(1) + * KABI_RESERVE(2) + * }; + * + * KABI_USE + * Simple wrappers to replace standard openEuler reserved elements. + * + * KABI_AUX_EMBED + * KABI_AUX_PTR + * Adds an extenstion of a struct in the form of "auxiliary structure". + * This is done prior to kABI freeze for structs that cannot be expanded + * later using KABI_EXTEND. See also KABI_RESERVED, these two + * approaches can (and often are) combined. + * + * To use this for 'struct foo' (the "base structure"), define a new + * structure called 'struct foo_rh'; this new struct is called "auxiliary + * structure". Then add KABI_AUX_EMBED or KABI_AUX_PTR to the end + * of the base structure. The argument is the name of the base structure, + * without the 'struct' keyword. + * + * KABI_AUX_PTR stores a pointer to the aux structure in the base + * struct. The lifecycle of the aux struct needs to be properly taken + * care of. + * + * KABI_AUX_EMBED embeds the aux struct into the base struct. This + * cannot be used when the base struct is itself embedded into another + * struct, allocated in an array, etc. + * + * Both approaches (ptr and embed) work correctly even when the aux struct + * is allocated by modules. To ensure this, the code responsible for + * allocation/assignment of the aux struct has to properly set the size of + * the aux struct; see the KABI_AUX_SET_SIZE and KABI_AUX_INIT_SIZE + * macros. + * + * New fields can be later added to the auxiliary structure, always to its + * end. Note the auxiliary structure cannot be shrunk in size later (i.e., + * fields cannot be removed, only deprecated). Any code accessing fields + * from the aux struct must guard the access using the KABI_AUX macro. + * The access itself is then done via a '_rh' field in the base struct. + * + * The auxiliary structure is not guaranteed for access by modules unless + * explicitly commented as such in the declaration of the aux struct + * itself or some of its elements. + * + * Example: + * + * struct foo_rh { + * int newly_added; + * }; + * + * struct foo { + * bool big_hammer; + * KABI_AUX_PTR(foo) + * }; + * + * void use(struct foo *f) + * { + * if (KABI_AUX(f, foo, newly_added)) + * f->_rh->newly_added = 123; + * else + * // the field 'newly_added' is not present in the passed + * // struct, fall back to old behavior + * f->big_hammer = true; + * } + * + * static struct foo_rh my_foo_rh { + * .newly_added = 0; + * } + * + * static struct foo my_foo = { + * .big_hammer = false, + * ._rh = &my_foo_rh, + * KABI_AUX_INIT_SIZE(foo) + * }; + * + * KABI_USE_AUX_PTR + * Creates an auxiliary structure post kABI freeze. This works by using + * two reserved fields (thus there has to be two reserved fields still + * available) and converting them to KABI_AUX_PTR. + * + * Example: + * + * struct foo_rh { + * }; + * + * struct foo { + * int a; + * KABI_RESERVE(1) + * KABI_USE_AUX_PTR(2, 3, foo) + * }; + * + * KABI_AUX_SET_SIZE + * KABI_AUX_INIT_SIZE + * Calculates and stores the size of the auxiliary structure. + * + * KABI_AUX_SET_SIZE is for dynamically allocated base structs, + * KABI_AUX_INIT_SIZE is for statically allocated case structs. + * + * These macros must be called from the allocation (KABI_AUX_SET_SIZE) + * or declaration (KABI_AUX_INIT_SIZE) site, regardless of whether + * that happens in the kernel or in a module. Without calling one of + * these macros, the aux struct will appear to have no fields to the + * kernel. + * + * Note: since KABI_AUX_SET_SIZE is intended to be invoked outside of + * a struct definition, it does not add the semicolon and must be + * terminated by semicolon by the caller. + * + * KABI_AUX + * Verifies that the given field exists in the given auxiliary structure. + * This MUST be called prior to accessing that field; failing to do that + * may lead to invalid memory access. + * + * The first argument is a pointer to the base struct, the second argument + * is the name of the base struct (without the 'struct' keyword), the + * third argument is the field name. + * + * This macro works for structs extended by either of KABI_AUX_EMBED, + * KABI_AUX_PTR and KABI_USE_AUX_PTR. + * + * KABI_FORCE_CHANGE + * Force change of the symbol checksum. The argument of the macro is a + * version for cases we need to do this more than once. + * + * This macro does the opposite: it changes the symbol checksum without + * actually changing anything about the exported symbol. It is useful for + * symbols that are not whitelisted, we're changing them in an + * incompatible way and want to prevent 3rd party modules to silently + * corrupt memory. Instead, by changing the symbol checksum, such modules + * won't be loaded by the kernel. This macro should only be used as a + * last resort when all other KABI workarounds have failed. + * + * KABI_EXCLUDE + * !!! WARNING: DANGEROUS, DO NOT USE unless you are aware of all the !!! + * !!! implications. This should be used ONLY EXCEPTIONALLY and only !!! + * !!! under specific circumstances. Very likely, this macro does not !!! + * !!! do what you expect it to do. Note that any usage of this macro !!! + * !!! MUST be paired with a KABI_FORCE_CHANGE annotation of !!! + * !!! a suitable symbol (or an equivalent safeguard) and the commit !!! + * !!! log MUST explain why the chosen solution is appropriate. !!! + * + * Exclude the element from checksum generation. Any such element is + * considered not to be part of the kABI whitelist and may be changed at + * will. Note however that it's the responsibility of the developer + * changing the element to ensure 3rd party drivers using this element + * won't panic, for example by not allowing them to be loaded. That can + * be achieved by changing another, non-whitelisted symbol they use, + * either by nature of the change or by using KABI_FORCE_CHANGE. + * + * Also note that any change to the element must preserve its size. Change + * of the size is not allowed and would constitute a silent kABI breakage. + * Beware that the KABI_EXCLUDE macro does not do any size checks. + * + * KABI_BROKEN_INSERT + * KABI_BROKEN_REMOVE + * Insert a field to the middle of a struct / delete a field from a struct. + * Note that this breaks kABI! It can be done only when it's certain that + * no 3rd party driver can validly reach into the struct. A typical + * example is a struct that is: both (a) referenced only through a long + * chain of pointers from another struct that is part of a whitelisted + * symbol and (b) kernel internal only, it should have never been visible + * to genksyms in the first place. + * + * Another example are structs that are explicitly exempt from kABI + * guarantee but we did not have enough foresight to use KABI_EXCLUDE. + * In this case, the warning for KABI_EXCLUDE applies. + * + * A detailed explanation of correctness of every KABI_BROKEN_* macro + * use is especially important. + * + * KABI_BROKEN_INSERT_BLOCK + * KABI_BROKEN_REMOVE_BLOCK + * A version of KABI_BROKEN_INSERT / REMOVE that allows multiple fields + * to be inserted or removed together. All fields need to be terminated + * by ';' inside(!) the macro parameter. The macro itself must not be + * terminated by ';'. + * + * KABI_BROKEN_REPLACE + * Replace a field by a different one without doing any checking. This + * allows replacing a field by another with a different size. Similarly + * to other KABI_BROKEN macros, use of this indicates a kABI breakage. + * + * KABI_BROKEN_INSERT_ENUM + * KABI_BROKEN_REMOVE_ENUM + * Insert a field to the middle of an enumaration type / delete a field from + * an enumaration type. Note that this can break kABI especially if the + * number of enum fields is used in an array within a structure. It can be + * done only when it is certain that no 3rd party driver will use the + * enumeration type or a structure that embeds an array with size determined + * by an enumeration type. + * + * KABI_EXTEND_ENUM + * Adds a new field to an enumeration type. This must always be added to + * the end of the enum. Before using this macro, make sure this is actually + * safe to do. + */ +#ifdef __GENKSYMS__ + +# define KABI_CONST +# define KABI_ADD_MODIFIER(_new) +# define KABI_EXTEND(_new) +# define KABI_FILL_HOLE(_new) +# define KABI_FORCE_CHANGE(ver) __attribute__((kabi_change ## ver)) +# define KABI_RENAME(_orig, _new) _orig +# define KABI_HIDE_INCLUDE(_file) <linux/kabi.h> +# define KABI_FAKE_INCLUDE(_file) _file +# define KABI_BROKEN_INSERT(_new) +# define KABI_BROKEN_REMOVE(_orig) _orig; +# define KABI_BROKEN_INSERT_BLOCK(_new) +# define KABI_BROKEN_REMOVE_BLOCK(_orig) _orig +# define KABI_BROKEN_REPLACE(_orig, _new) _orig; +# define KABI_BROKEN_INSERT_ENUM(_new) +# define KABI_BROKEN_REMOVE_ENUM(_orig) _orig, +# define KABI_EXTEND_ENUM(_new) + +# define _KABI_DEPRECATE(_type, _orig) _type _orig +# define _KABI_DEPRECATE_FN(_type, _orig, _args...) _type (*_orig)(_args) +# define _KABI_REPLACE(_orig, _new) _orig +# define _KABI_EXCLUDE(_elem) + +#else + +# define KABI_ALIGN_WARNING ". Disable CONFIG_KABI_SIZE_ALIGN_CHECKS if debugging." + +# define KABI_CONST const +# define KABI_ADD_MODIFIER(_new) _new +# define KABI_EXTEND(_new) _new; +# define KABI_FILL_HOLE(_new) _new; +# define KABI_FORCE_CHANGE(ver) +# define KABI_RENAME(_orig, _new) _new +# define KABI_HIDE_INCLUDE(_file) _file +# define KABI_FAKE_INCLUDE(_file) <linux/kabi.h> +# define KABI_BROKEN_INSERT(_new) _new; +# define KABI_BROKEN_REMOVE(_orig) +# define KABI_BROKEN_INSERT_BLOCK(_new) _new +# define KABI_BROKEN_REMOVE_BLOCK(_orig) +# define KABI_BROKEN_REPLACE(_orig, _new) _new; +# define KABI_BROKEN_INSERT_ENUM(_new) _new, +# define KABI_BROKEN_REMOVE_ENUM(_orig) +# define KABI_EXTEND_ENUM(_new) _new, + +#if IS_BUILTIN(CONFIG_KABI_SIZE_ALIGN_CHECKS) +# define __KABI_CHECK_SIZE_ALIGN(_orig, _new) \ + union { \ + _Static_assert(sizeof(struct{_new;}) <= sizeof(struct{_orig;}), \ + __FILE__ ":" __stringify(__LINE__) ": " __stringify(_new) " is larger than " __stringify(_orig) KABI_ALIGN_WARNING); \ + _Static_assert(__alignof__(struct{_new;}) <= __alignof__(struct{_orig;}), \ + __FILE__ ":" __stringify(__LINE__) ": " __stringify(_orig) " is not aligned the same as " __stringify(_new) KABI_ALIGN_WARNING); \ + } +# define __ABI_CHECK_SIZE(_item, _size) \ + _Static_assert(sizeof(struct{_item;}) <= _size, \ + __FILE__ ":" __stringify(__LINE__) ": " __stringify(_item) " is larger than the reserved size (" __stringify(_size) " bytes)" KABI_ALIGN_WARNING) +#else +# define __KABI_CHECK_SIZE_ALIGN(_orig, _new) +# define __KABI_CHECK_SIZE(_item, _size) +#endif + +# define _KABI_DEPRECATE(_type, _orig) _type kabi_reserved_##_orig +# define _KABI_DEPRECATE_FN(_type, _orig, _args...) \ + _type (* kabi_reserved_##_orig)(_args) +# define _KABI_REPLACE(_orig, _new) \ + union { \ + _new; \ + struct { \ + _orig; \ + } __UNIQUE_ID(kabi_hide); \ + __KABI_CHECK_SIZE_ALIGN(_orig, _new); \ + } + +# define _KABI_EXCLUDE(_elem) _elem + +#endif /* __GENKSYMS__ */ + +/* semicolon added wrappers for the KABI_REPLACE macros */ +# define KABI_DEPRECATE(_type, _orig) _KABI_DEPRECATE(_type, _orig); +# define KABI_DEPRECATE_FN(_type, _orig, _args...) \ + _KABI_DEPRECATE_FN(_type, _orig, _args); +# define KABI_REPLACE(_orig, _new) _KABI_REPLACE(_orig, _new); +/* + * Macro for breaking up a random element into two smaller chunks using an + * anonymous struct inside an anonymous union. + */ +# define KABI_REPLACE2(orig, _new1, _new2) KABI_REPLACE(orig, struct{ _new1; _new2;}) + +/* + * We tried to standardize on openEuler reserved names. These wrappers + * leverage those common names making it easier to read and find in the + * code. + */ +# define _KABI_RESERVE(n) unsigned long kabi_reserved##n +# define KABI_RESERVE(n) _KABI_RESERVE(n); +/* + * Simple wrappers to replace standard openEuler reserved elements. + */ +# define KABI_USE(n, _new) KABI_REPLACE(_KABI_RESERVE(n), _new) +/* + * Macros for breaking up a reserved element into two smaller chunks using + * an anonymous struct inside an anonymous union. + */ +# define KABI_USE2(n, _new1, _new2) KABI_REPLACE(_KABI_RESERVE(n), struct{ _new1; _new2; }) + +#define KABI_EXCLUDE(_elem) _KABI_EXCLUDE(_elem); + +#define KABI_EXTEND_WITH_SIZE(_new, _size) \ + KABI_EXTEND(union { \ + _new; \ + unsigned long KABI_UNIQUE_ID[_size]; \ + __KABI_CHECK_SIZE(_new, 8 * (_size)); \ + }) + +#define _KABI_AUX_PTR(_struct) \ + size_t _struct##_size_rh; \ + _KABI_EXCLUDE(struct _struct##_rh *_rh) +#define KABI_AUX_PTR(_struct) \ + _KABI_AUX_PTR(_struct); + +#define _KABI_AUX_EMBED(_struct) \ + size_t _struct##_size_rh; \ + _KABI_EXCLUDE(struct _struct##_rh _rh) +#define KABI_AUX_EMBED(_struct) \ + _KABI_AUX_EMBED(_struct); + +#define KABI_USE_AUX_PTR(n1, n2, _struct) \ + KABI_USE(n1, n2, \ + struct { KABI_AUX_PTR(_struct) }) + +/* + * KABI_AUX_SET_SIZE calculates and sets the size of the extended struct and + * stores it in the size_rh field for structs that are dynamically allocated. + * This macro MUST be called when expanding a base struct with + * KABI_SIZE_AND_EXTEND, and it MUST be called from the allocation site + * regardless of being allocated in the kernel or a module. + * Note: since this macro is intended to be invoked outside of a struct, + * a semicolon is necessary at the end of the line where it is invoked. + */ +#define KABI_AUX_SET_SIZE(_name, _struct) ({ \ + (_name)->_struct##_size_rh = sizeof(struct _struct##_rh); \ +}) + +/* + * KABI_AUX_INIT_SIZE calculates and sets the size of the extended struct and + * stores it in the size_rh field for structs that are statically allocated. + * This macro MUST be called when expanding a base struct with + * KABI_SIZE_AND_EXTEND, and it MUST be called from the declaration site + * regardless of being allocated in the kernel or a module. + */ +#define KABI_AUX_INIT_SIZE(_struct) \ + ._struct##_size_rh = sizeof(struct _struct##_rh), + +/* + * KABI_AUX verifies allocated memory exists. This MUST be called to + * verify that memory in the _rh struct is valid, and can be called + * regardless if KABI_SIZE_AND_EXTEND or KABI_SIZE_AND_EXTEND_PTR is + * used. + */ +#define KABI_AUX(_ptr, _struct, _field) ({ \ + size_t __off = offsetof(struct _struct##_rh, _field); \ + (_ptr)->_struct##_size_rh > __off ? true : false; \ +}) + +#endif /* _LINUX_KABI_H */
From: Xie XiuQi xiexiuqi@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
--------------------------------
This option enables more stringent kabi checks. Those must be disable in case of a debug-build because they allow to change struct sizes.
Signed-off-by: Xie XiuQi xiexiuqi@huawei.com Reviewed-by: Cheng Jian cj.chengjian@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/Kconfig b/Kconfig index 745bc773f567..bb409bb587b0 100644 --- a/Kconfig +++ b/Kconfig @@ -30,3 +30,10 @@ source "lib/Kconfig" source "lib/Kconfig.debug"
source "Documentation/Kconfig" + +config KABI_SIZE_ALIGN_CHECKS + bool "Enables more stringent kabi checks in the macros" + default y + help + This option enables more stringent kabi checks. Those must be disable + in case of a debug-build because they allow to change struct sizes.
From: Xie XiuQi xiexiuqi@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
--------------------------------
This option enables more stringent kabi checks. Those must be disable in case of a debug-build because they allow to change struct sizes.
We enable this option by default.
Signed-off-by: Xie XiuQi xiexiuqi@huawei.com Reviewed-by: Cheng Jian cj.chengjian@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com
Conflicts: arch/arm64/configs/openeuler_defconfig arch/x86/configs/openeuler_defconfig
Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 + arch/x86/configs/openeuler_defconfig | 1 + 2 files changed, 2 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 8f1a4db8d49b..a1d6447b0e59 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -7940,3 +7940,4 @@ CONFIG_ARCH_USE_MEMTEST=y # # end of Rust hacking # end of Kernel hacking +CONFIG_KABI_SIZE_ALIGN_CHECKS=y diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index 507d199ff598..a0ca8880563c 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -9156,3 +9156,4 @@ CONFIG_ARCH_USE_MEMTEST=y # # end of Rust hacking # end of Kernel hacking +CONFIG_KABI_SIZE_ALIGN_CHECKS=y
From: Zheng Zengkai zhengzengkai@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
-----------------------
Add CONFIG_KABI_RESERVE to control KABI padding reserve or not, for some embedded system, KABI padding reserve may be not necessary.
By the way, adjust unsigned long to u64 to unify basic reserve length for both 32bit and 64bit architectures.
Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- Kconfig | 8 ++++++++ include/linux/kabi.h | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/Kconfig b/Kconfig index bb409bb587b0..9c9b5fedd43c 100644 --- a/Kconfig +++ b/Kconfig @@ -37,3 +37,11 @@ config KABI_SIZE_ALIGN_CHECKS help This option enables more stringent kabi checks. Those must be disable in case of a debug-build because they allow to change struct sizes. + +config KABI_RESERVE + bool "Enable KABI PADDING RESERVE" + default y + help + This option enables KABI padding reserve. + For some embedded system, KABI padding reserve may be not necessary. + Disable it on demand. diff --git a/include/linux/kabi.h b/include/linux/kabi.h index da5e6d71e66b..1abfcc8e0275 100644 --- a/include/linux/kabi.h +++ b/include/linux/kabi.h @@ -396,6 +396,7 @@ # define _KABI_DEPRECATE(_type, _orig) _type kabi_reserved_##_orig # define _KABI_DEPRECATE_FN(_type, _orig, _args...) \ _type (* kabi_reserved_##_orig)(_args) +#ifdef CONFIG_KABI_RESERVE # define _KABI_REPLACE(_orig, _new) \ union { \ _new; \ @@ -404,6 +405,9 @@ } __UNIQUE_ID(kabi_hide); \ __KABI_CHECK_SIZE_ALIGN(_orig, _new); \ } +#else +# define _KABI_REPLACE(_orig, _new) KABI_BROKEN_REPLACE(_orig, _new) +#endif
# define _KABI_EXCLUDE(_elem) _elem
@@ -425,7 +429,11 @@ * leverage those common names making it easier to read and find in the * code. */ -# define _KABI_RESERVE(n) unsigned long kabi_reserved##n +#ifdef CONFIG_KABI_RESERVE +# define _KABI_RESERVE(n) u64 kabi_reserved##n +#else +# define _KABI_RESERVE(n) +#endif # define KABI_RESERVE(n) _KABI_RESERVE(n); /* * Simple wrappers to replace standard openEuler reserved elements.
From: Zheng Zengkai zhengzengkai@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
---------------------------
Enable CONFIG_KABI_RESERVE for x86 and arm64 architectures in openeuler_defconfig by default.
Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 + arch/x86/configs/openeuler_defconfig | 1 + 2 files changed, 2 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index a1d6447b0e59..ca668f33d46b 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -7941,3 +7941,4 @@ CONFIG_ARCH_USE_MEMTEST=y # end of Rust hacking # end of Kernel hacking CONFIG_KABI_SIZE_ALIGN_CHECKS=y +CONFIG_KABI_RESERVE=y diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index a0ca8880563c..ea53a8016c09 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -9157,3 +9157,4 @@ CONFIG_ARCH_USE_MEMTEST=y # end of Rust hacking # end of Kernel hacking CONFIG_KABI_SIZE_ALIGN_CHECKS=y +CONFIG_KABI_RESERVE=y
From: Zheng Zengkai zhengzengkai@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
--------------------------
Generalize naming of some kabi helper macros.
Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- include/linux/kabi.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/include/linux/kabi.h b/include/linux/kabi.h index 1abfcc8e0275..a52d9fa72cfa 100644 --- a/include/linux/kabi.h +++ b/include/linux/kabi.h @@ -151,7 +151,7 @@ * approaches can (and often are) combined. * * To use this for 'struct foo' (the "base structure"), define a new - * structure called 'struct foo_rh'; this new struct is called "auxiliary + * structure called 'struct foo_resvd'; this new struct is called "auxiliary * structure". Then add KABI_AUX_EMBED or KABI_AUX_PTR to the end * of the base structure. The argument is the name of the base structure, * without the 'struct' keyword. @@ -174,7 +174,7 @@ * end. Note the auxiliary structure cannot be shrunk in size later (i.e., * fields cannot be removed, only deprecated). Any code accessing fields * from the aux struct must guard the access using the KABI_AUX macro. - * The access itself is then done via a '_rh' field in the base struct. + * The access itself is then done via a '_resvd' field in the base struct. * * The auxiliary structure is not guaranteed for access by modules unless * explicitly commented as such in the declaration of the aux struct @@ -182,7 +182,7 @@ * * Example: * - * struct foo_rh { + * struct foo_resvd { * int newly_added; * }; * @@ -194,20 +194,20 @@ * void use(struct foo *f) * { * if (KABI_AUX(f, foo, newly_added)) - * f->_rh->newly_added = 123; + * f->_resvd->newly_added = 123; * else * // the field 'newly_added' is not present in the passed * // struct, fall back to old behavior * f->big_hammer = true; * } * - * static struct foo_rh my_foo_rh { + * static struct foo_resvd my_foo_resvd { * .newly_added = 0; * } * * static struct foo my_foo = { * .big_hammer = false, - * ._rh = &my_foo_rh, + * ._resvd = &my_foo_resvd, * KABI_AUX_INIT_SIZE(foo) * }; * @@ -218,7 +218,7 @@ * * Example: * - * struct foo_rh { + * struct foo_resvd { * }; * * struct foo { @@ -385,7 +385,7 @@ _Static_assert(__alignof__(struct{_new;}) <= __alignof__(struct{_orig;}), \ __FILE__ ":" __stringify(__LINE__) ": " __stringify(_orig) " is not aligned the same as " __stringify(_new) KABI_ALIGN_WARNING); \ } -# define __ABI_CHECK_SIZE(_item, _size) \ +# define __KABI_CHECK_SIZE(_item, _size) \ _Static_assert(sizeof(struct{_item;}) <= _size, \ __FILE__ ":" __stringify(__LINE__) ": " __stringify(_item) " is larger than the reserved size (" __stringify(_size) " bytes)" KABI_ALIGN_WARNING) #else @@ -455,14 +455,14 @@ })
#define _KABI_AUX_PTR(_struct) \ - size_t _struct##_size_rh; \ - _KABI_EXCLUDE(struct _struct##_rh *_rh) + size_t _struct##_size_resvd; \ + _KABI_EXCLUDE(struct _struct##_resvd *_resvd) #define KABI_AUX_PTR(_struct) \ _KABI_AUX_PTR(_struct);
#define _KABI_AUX_EMBED(_struct) \ - size_t _struct##_size_rh; \ - _KABI_EXCLUDE(struct _struct##_rh _rh) + size_t _struct##_size_resvd; \ + _KABI_EXCLUDE(struct _struct##_resvd _resvd) #define KABI_AUX_EMBED(_struct) \ _KABI_AUX_EMBED(_struct);
@@ -472,7 +472,7 @@
/* * KABI_AUX_SET_SIZE calculates and sets the size of the extended struct and - * stores it in the size_rh field for structs that are dynamically allocated. + * stores it in the size_resvd field for structs that are dynamically allocated. * This macro MUST be called when expanding a base struct with * KABI_SIZE_AND_EXTEND, and it MUST be called from the allocation site * regardless of being allocated in the kernel or a module. @@ -480,28 +480,28 @@ * a semicolon is necessary at the end of the line where it is invoked. */ #define KABI_AUX_SET_SIZE(_name, _struct) ({ \ - (_name)->_struct##_size_rh = sizeof(struct _struct##_rh); \ + (_name)->_struct##_size_resvd = sizeof(struct _struct##_resvd); \ })
/* * KABI_AUX_INIT_SIZE calculates and sets the size of the extended struct and - * stores it in the size_rh field for structs that are statically allocated. + * stores it in the size_resvd field for structs that are statically allocated. * This macro MUST be called when expanding a base struct with * KABI_SIZE_AND_EXTEND, and it MUST be called from the declaration site * regardless of being allocated in the kernel or a module. */ #define KABI_AUX_INIT_SIZE(_struct) \ - ._struct##_size_rh = sizeof(struct _struct##_rh), + ._struct##_size_resvd = sizeof(struct _struct##_resvd),
/* * KABI_AUX verifies allocated memory exists. This MUST be called to - * verify that memory in the _rh struct is valid, and can be called + * verify that memory in the _resvd struct is valid, and can be called * regardless if KABI_SIZE_AND_EXTEND or KABI_SIZE_AND_EXTEND_PTR is * used. */ #define KABI_AUX(_ptr, _struct, _field) ({ \ - size_t __off = offsetof(struct _struct##_rh, _field); \ - (_ptr)->_struct##_size_rh > __off ? true : false; \ + size_t __off = offsetof(struct _struct##_resvd, _field); \ + (_ptr)->_struct##_size_resvd > __off ? true : false; \ })
#endif /* _LINUX_KABI_H */
From: Li Lingfeng lilingfeng3@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
Reference: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/commit/...
---------------------------
We don't really need the field names to be globally unique, it is enough when they are unique in the given struct. Since structs do not generally span mutliple files, using the line number is enough to ensure an unique identifier. It means that we can't use two KABI_RENAME macros on the same line but that's not happening anyway.
This allows pahole to deduplicate the type info of structs using KABI macros, lowering the size of vmlinuz from 26M to 8.5
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Reviewed-by: zhihao Cheng chengzhihao1@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- include/linux/kabi.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/linux/kabi.h b/include/linux/kabi.h index a52d9fa72cfa..fe3213c0f576 100644 --- a/include/linux/kabi.h +++ b/include/linux/kabi.h @@ -393,6 +393,8 @@ # define __KABI_CHECK_SIZE(_item, _size) #endif
+#define KABI_UNIQUE_ID __PASTE(kabi_hidden_, __LINE__) + # define _KABI_DEPRECATE(_type, _orig) _type kabi_reserved_##_orig # define _KABI_DEPRECATE_FN(_type, _orig, _args...) \ _type (* kabi_reserved_##_orig)(_args) @@ -402,7 +404,7 @@ _new; \ struct { \ _orig; \ - } __UNIQUE_ID(kabi_hide); \ + } KABI_UNIQUE_ID; \ __KABI_CHECK_SIZE_ALIGN(_orig, _new); \ } #else
From: Xie XiuQi xiexiuqi@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
---------------------------
Add a tool to generate the kabi reference relationship for given module list.
1) ./scripts/kabisyms -k <symlist> -s <symvers> -o <output>
Generate Module.kabi file via symbol list.
2) ./scripts/kabisyms -k <symlist> -d <kabideps> -o <output>
memset: 3: nvme-core.ko nvme-fc.ko nvme.ko nvmet.ko complete: 4: nvme-rdma.ko nvme-fc.ko nvme.ko nvme-fcloop.ko mutex_unlock: 3: nvme-rdma.ko nvme-core.ko nvme.ko init_timer_key: 3: nvme-rdma.ko nvme-core.ko nvme-fc.ko nvmet.ko mutex_lock: 2: nvme-rdma.ko nvme-core.ko
Signed-off-by: Xie XiuQi xiexiuqi@huawei.com Reviewed-by: Tan Xiaojun tanxiaojun@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- scripts/kabisyms | 141 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100755 scripts/kabisyms
diff --git a/scripts/kabisyms b/scripts/kabisyms new file mode 100755 index 000000000000..dcba08e64a26 --- /dev/null +++ b/scripts/kabisyms @@ -0,0 +1,141 @@ +#!/usr/bin/perl -w +# SPDX-License-Identifier: GPL-2.0 +# +# kabisyms - a script tools to generate kabi baseline and check symbol +# referance relationship. +# +# Author: Xie XiuQi xiexiuqi@huawei.com +# Copyright (C) 2019 Huawei, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# General Public License (GPL). +# +# usage: +# ./scripts/kabisyms -k <symlist> -s <symvers> -o <output> +# ./scripts/kabisyms -k <symlist> -d <kabideps> -o <output> + +use 5.010; + +use strict; +use Getopt::Long; +use File::Basename; + +my $SYMLIST; +my $SYMVERS; +my $KABIDEPS; +my $OUTPUT = "Module.kabi"; +my $VERBOSE; + +my $PROG = basename $0; + +sub usage { + say "usage:"; + say " $PROG [--symlist|k] [--symvers|s] [--kabideps|d] [--output|o] [--verbose|v] [--help|h|?]"; + say " -k|--symlist"; + say " symbol list (filename)"; + say " -s|--symvers"; + say " Module.symvers"; + say " -d|--kabideps"; + say " kabideps"; + say " -o|--output"; + say " filename of output"; + say " -v|--verbose:"; + say " show more info"; + say " -h|-?|--help:"; + say " show this usage"; + say " examples:"; + say " ./scripts/kabisyms -k <symlist> -s <symvers> -o <output>"; + say " ./scripts/kabisyms -k <symlist> -d <kabideps> -o <output>"; + exit 0; +} + +usage() unless (@ARGV); +my $result = GetOptions( + 'symlist|k=s' => $SYMLIST, + 'symvers|s=s' => $SYMVERS, + 'kabideps|d=s' => $KABIDEPS, + 'output|o=s' => $OUTPUT, + 'verbose|v!' => $VERBOSE, + 'help|h|?' => &usage, +) or usage(); + +my @syms; +my @symvers; +my @kabideps; + +if ($SYMLIST) { + @syms = `cat $SYMLIST`; chomp @syms; +} +else { + usage(); +} + +if ($SYMVERS) { + @symvers = `cat $SYMVERS`; chomp @symvers; +} +elsif ($KABIDEPS) { + @kabideps = `cat $KABIDEPS`; chomp @kabideps; +} +else { + usage(); +} + +sub check_sym { + my $sym = shift; + my @res; + my $found; + + foreach (@symvers) { + if (/^\s*$/) { + next; + } + + if (/^0x[0-9a-fA-F]+\s+$sym\s+/) { + printf OUT "%s\n", $_; + $found = 1; + last; + } + } + + printf "%s is not included in %s\n", $sym, $SYMVERS if (!$found); +} + +sub check_deps { + my $sym = shift; + my @res; + my $found; + + foreach (@kabideps) { + if (/^\s*$/) { + next; + } + + if (/^\s*$sym:/) { + printf OUT "%s\n", $_; + $found = 1; + last; + } + } + + printf "%s is not included in %s\n", $sym, $KABIDEPS if (!$found); +} + +my $output = $OUTPUT; + +open(OUT, ">", "$output") + || die "can't open >$output : $!"; + +my $total = @syms; +my $count; +for (@syms) { + if ($SYMVERS) { + check_sym($_); + } + elsif ($KABIDEPS) { + check_deps($_); + } + printf "\r%d/%d", ++$count, $total if ($VERBOSE); +} +printf "output to %s\n", $OUTPUT; + +close OUT;
From: Xie XiuQi xiexiuqi@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
---------------------------
Add a tool to generate the kabi reference relationship for given module list.
Like this:
memset: 3: nvme-core.ko nvme-fc.ko nvme.ko nvmet.ko complete: 4: nvme-rdma.ko nvme-fc.ko nvme.ko nvme-fcloop.ko mutex_unlock: 3: nvme-rdma.ko nvme-core.ko nvme.ko init_timer_key: 3: nvme-rdma.ko nvme-core.ko nvme-fc.ko nvmet.ko mutex_lock: 2: nvme-rdma.ko nvme-core.ko
usage: ./scripts/kabideps -m <mod list> -s <symvers> -d <dir of modules> -e
Signed-off-by: Xie XiuQi xiexiuqi@huawei.com Reviewed-by: Hanjun Guo guohanjun@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- scripts/kabideps | 161 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100755 scripts/kabideps
diff --git a/scripts/kabideps b/scripts/kabideps new file mode 100755 index 000000000000..210b79e761eb --- /dev/null +++ b/scripts/kabideps @@ -0,0 +1,161 @@ +#!/usr/bin/perl -w +# SPDX-License-Identifier: GPL-2.0 +# +# kabideps - a script tools to generate symbol referenced by other modules +# +# We use this script to check against reference Module.kabi files. +# +# Author: Xie XiuQi xiexiuqi@huawei.com +# Copyright (C) 2019 Huawei, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# General Public License (GPL). +# +# usage: +# ./scripts/kabideps -m <module list> -s <symvers> -d <basedir of modules> -e + +use 5.010; + +use strict; +use Getopt::Long; +use File::Basename; + +my $MODULES; +my $SYMVERS; +my $EXCLUDE; +my $BASEDIR; +my $VERBOSE; + +my $PROG = basename $0; + +sub usage { + say "usage:"; + say " $PROG [--modules|m] [--symvers|s] [--basedir|d] [--exclude|e] [--verbose|v] [--help|h|?]"; + say " -m|--module"; + say " module list to be check (filename)"; + say " -d|--basedir"; + say " dir of ko"; + say " -s|--symvers"; + say " Module.symvers"; + say " -e|--exclude"; + say " exclude symbols which exported by the modules themselves"; + say " -v|--verbose:"; + say " show more info"; + say " -h|-?|--help:"; + say " show this usage"; + exit 0; +} + +usage() unless (@ARGV); +my $result = GetOptions( + 'module|m=s' => $MODULES, + 'basedir|d=s' => $BASEDIR, + 'symvers|s=s' => $SYMVERS, + 'exclude|e!' => $EXCLUDE, + 'verbose|v!' => $VERBOSE, + 'help|h|?' => &usage, +) or usage(); + +my @mods; + +if ($MODULES) { + @mods = `cat $MODULES`; chomp @mods; +} +else { + @mods = `find $BASEDIR |grep -E ".ko$"`; chomp @mods; +} + +my @allsyms = exclude_check(); +my $allmodsyms = {}; + +sub check_sym { + my $sym = shift; + my @res; + + foreach my $m (@mods) { + my @kmodsyms; + my $modname = basename $m; + + if ($m =~ /^\s*$/) { + next; + } + + if (!$allmodsyms->{$m}) { + @kmodsyms = `modprobe --dump-modversions $m |awk '{print $2}'`; chomp @kmodsyms; + $allmodsyms->{$m} = @kmodsyms; + } + + my $syms = $allmodsyms->{$m}; + for (@{$syms}) { + if ($sym eq $_) { + push @res, $modname; + } + } + } + + my $num = @res; + printf OUT "%d: ", $num; + for (@res) { + printf OUT "%s ", $_; + } +} + +sub exclude_check { + my @syms; + my @res; + my $i; + + if ($EXCLUDE) { + @syms = `cat $SYMVERS`; chomp @syms; + } + else { + @res = `cat $SYMVERS |awk '{print $2}'`; chomp @syms; + + return @res; + } + + my $total = @syms; + my $count; + say "excluding symbols exported by modules themselves..."; + for ($i = 0; $i < @syms; $i++) { + my @words = split(/\s+/, $syms[$i]); + my $found = 0; + + foreach my $mod (@mods) { + my $m; + + $words[2] = basename $words[2]; + $m = basename $mod; + $m =~ s/.ko$//g; + + if ($words[2] eq $m) { + $found = 1; + last; + } + } + push @res, $words[1] unless($found); + + printf "\r%d/%d", $count++, $total; + } + print "\n"; + + return @res; +} + +my $output = "kabideps.txt"; + +open(OUT, ">", "$output") + || die "can't open >$output : $!"; + +my $total = @allsyms; +my $count; +say "checking symbols ..."; +for (@allsyms) { + printf OUT "%s: ", $_; + check_sym($_); + print OUT "\n"; + + printf "\r%d/%d", $count++, $total; +} + +close OUT;
From: Xie XiuQi xiexiuqi@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8LQBH
---------------------------
Add check-kabi tool to detect the kabi changes introduced by the patch.
Usage: ./scripts/check-kabi -k Module.symvers.baseline -s Module.symvers
This tool is ported from CentOS 7.x source packages.
Signed-off-by: Xie XiuQi xiexiuqi@huawei.com Reviewed-by: Li Bin huawei.libin@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- scripts/check-kabi | 147 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100755 scripts/check-kabi
diff --git a/scripts/check-kabi b/scripts/check-kabi new file mode 100755 index 000000000000..b1b55d512e61 --- /dev/null +++ b/scripts/check-kabi @@ -0,0 +1,147 @@ +#!/usr/bin/python +# SPDX-License-Identifier: GPL-2.0 +# +# check-kabi - Red Hat kABI reference checking tool +# +# We use this script to check against reference Module.kabi files. +# +# Author: Jon Masters jcm@redhat.com +# Copyright (C) 2007-2009 Red Hat, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# General Public License (GPL). + +# Changelog: +# +# 2009/08/15 - Updated for use in RHEL6. +# 2007/06/13 - Initial rewrite in python by Jon Masters. + +__author__ = "Jon Masters jcm@redhat.com" +__version__ = "2.0" +__date__ = "2009/08/15" +__copyright__ = "Copyright (C) 2007-2009 Red Hat, Inc" +__license__ = "GPL" + +import getopt +import os +import re +import string +import sys + +true = 1 +false = 0 + +def load_symvers(symvers,filename): + """Load a Module.symvers file.""" + + symvers_file = open(filename,"r") + + while true: + in_line = symvers_file.readline() + if in_line == "": + break + if in_line == "\n": + continue + checksum,symbol,directory,type,namespace = string.split(in_line, sep='\t') + + symvers[symbol] = in_line[0:-1] + +def load_kabi(kabi,filename): + """Load a Module.kabi file.""" + + kabi_file = open(filename,"r") + + while true: + in_line = kabi_file.readline() + if in_line == "": + break + if in_line == "\n": + continue + checksum,symbol,directory,type,namespace = string.split(in_line, sep='\t') + + kabi[symbol] = in_line[0:-1] + +def check_kabi(symvers,kabi): + """Check Module.kabi and Module.symvers files.""" + + fail=0 + warn=0 + changed_symbols=[] + moved_symbols=[] + + for symbol in kabi: + abi_hash,abi_sym,abi_dir,abi_type,namespace = string.split(kabi[symbol], sep='\t') + if symvers.has_key(symbol): + sym_hash,sym_sym,sym_dir,sym_type,namespace = string.split(symvers[symbol], sep='\t') + if abi_hash != sym_hash: + fail=1 + changed_symbols.append(symbol) + + if abi_dir != sym_dir: + warn=1 + moved_symbols.append(symbol) + else: + fail=1 + changed_symbols.append(symbol) + + if fail: + print "*** ERROR - ABI BREAKAGE WAS DETECTED ***" + print "" + print "The following symbols have been changed (this will cause an ABI breakage):" + print "" + for symbol in changed_symbols: + print symbol + print "" + + if warn: + print "*** WARNING - ABI SYMBOLS MOVED ***" + print "" + print "The following symbols moved (typically caused by moving a symbol from being" + print "provided by the kernel vmlinux out to a loadable module):" + print "" + for symbol in moved_symbols: + print symbol + print "" + + """Halt the build, if we got errors and/or warnings. In either case, + double-checkig is required to avoid introducing / concealing + KABI inconsistencies.""" + if fail or warn: + sys.exit(1) + sys.exit(0) + +def usage(): + print """ +check-kabi: check Module.kabi and Module.symvers files. + + check-kabi [ -k Module.kabi ] [ -s Module.symvers ] + +""" + +if __name__ == "__main__": + + symvers_file = "" + kabi_file = "" + + opts, args = getopt.getopt(sys.argv[1:], 'hk:s:') + + for o, v in opts: + if o == "-s": + symvers_file = v + if o == "-h": + usage() + sys.exit(0) + if o == "-k": + kabi_file = v + + if (symvers_file == "") or (kabi_file == ""): + usage() + sys.exit(1) + + symvers={} + kabi={} + + load_symvers(symvers,symvers_file) + load_kabi(kabi,kabi_file) + check_kabi(symvers,kabi) +
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/3238 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/A...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/3238 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/A...