mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
Kbuild updates for v6.8
- Make Kconfig parse the input .config more precisely - Support W=c and W=e options for Kconfig - Set Kconfig int/hex symbols to zero if the 'default' property is missing - Add .editorconfig - Add scripts/git.orderFile - Add a script to detect backward-incompatible changes in UAPI headers - Resolve the symlink passed to O= option properly - Use the user-supplied mtime for all files in the builtin initramfs, which provides better reproducible builds - Fix the direct execution of debian/rules for Debian package builds - Use build ID instead of the .gnu_debuglink section for the Debian dbg package -----BEGIN PGP SIGNATURE----- iQJJBAABCgAzFiEEbmPs18K1szRHjPqEPYsBB53g2wYFAmWnEQ8VHG1hc2FoaXJv eUBrZXJuZWwub3JnAAoJED2LAQed4NsGbn8P/RpJ6f4eYAVG/Jnsf5xkkuoOCdWP ADA9I5VfgiUzEZV48tjjUOOhk9LO/QDwlxtbLZjlo9jC5TI+IVrXzCu4ShRhmE+4 eM/VXFur9RN6CuNWNmkf7yzd0dawiwL4QR/0L82ZNmwXGymeEUzzmFviD5KfJRY8 z6bgA4jLu9qsHNzX8eYA2LU+jpOoNiRQAlGzTE0oDgQnv/ZXJB/H+8tEhzH85oZk F087IQCct25yGAbZhEkuX2PHx5kus9ICF72Pkqxh075aOQzfKIO8S3PPkt4nAiHK Cb6sahRcO7QwxH7MJVWgmfbXNMbs9p8fOj9Aiudl2EEWVRav1mw9UuA5kCnTh6vi LpI4bYNChl8fNTX2gX+Dfkmbc5r2Yl65ufW23VlRdZfdrXbJWlQbkkdvJeb7NoEj u6z26b/2WMaTecxr0Bw50PbleHYZwWIscN5lGoK6rgUU04mr4t8g1ejpcxfj+79S MfbpEvPGKMJjelRBHf2x4qzzHQZHeqIbaItCNt8wGSVipgTvrWED2UaaEnW02SoL pwIcBjV9xiUo8UUVil/R8W6xr/Ybv0lWYcIBzQjibiCzhFgw4adPnzZ6eTlaV+6e ne527SqxQ0gF3xgDhxOz4VUF/b4TlnVycArIl80Kk/sFd8jX+AObkCtamZEPc0Rz GjsorSF/s+Fw7XMp =HXZB -----END PGP SIGNATURE----- Merge tag 'kbuild-v6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild Pull Kbuild updates from Masahiro Yamada: - Make Kconfig parse the input .config more precisely - Support W=c and W=e options for Kconfig - Set Kconfig int/hex symbols to zero if the 'default' property is missing - Add .editorconfig - Add scripts/git.orderFile - Add a script to detect backward-incompatible changes in UAPI headers - Resolve the symlink passed to O= option properly - Use the user-supplied mtime for all files in the builtin initramfs, which provides better reproducible builds - Fix the direct execution of debian/rules for Debian package builds - Use build ID instead of the .gnu_debuglink section for the Debian dbg package * tag 'kbuild-v6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (53 commits) kbuild: deb-pkg: use debian/<package> for tmpdir kbuild: deb-pkg: move 'make headers' to build-arch kbuild: deb-pkg: do not search for 'scripts' directory under arch/ kbuild: deb-pkg: use build ID instead of debug link for dbg package kbuild: deb-pkg: use more debhelper commands in builddeb kbuild: deb-pkg: remove unneeded '-f $srctree/Makefile' in debian/rules kbuild: deb-pkg: allow to run debian/rules from output directory kbuild: deb-pkg: set DEB_* variables if debian/rules is directly executed kbuild: deb-pkg: squash scripts/package/deb-build-option to debian/rules kbuild: deb-pkg: factor out common Make options in debian/rules kbuild: deb-pkg: hard-code Build-Depends kbuild: deb-pkg: split debian/copyright from the mkdebian script gen_init_cpio: Apply mtime supplied by user to all file types kbuild: resolve symlinks for O= properly docs: dev-tools: Add UAPI checker documentation check-uapi: Introduce check-uapi.sh scripts: Introduce a default git.orderFile kconfig: WERROR unmet symbol dependency Add .editorconfig file for basic formatting kconfig: Use KCONFIG_CONFIG instead of .config ...
This commit is contained in:
commit
b5f66ba2d0
32
.editorconfig
Normal file
32
.editorconfig
Normal file
@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
root = true
|
||||
|
||||
[{*.{awk,c,dts,dtsi,dtso,h,mk,s,S},Kconfig,Makefile,Makefile.*}]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[*.{json,py,rs}]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# this must be below the general *.py to overwrite it
|
||||
[tools/{perf,power,rcu,testing/kunit}/**.py,]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[*.yaml]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = unset
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -96,6 +96,7 @@ modules.order
|
||||
#
|
||||
!.clang-format
|
||||
!.cocciconfig
|
||||
!.editorconfig
|
||||
!.get_maintainer.ignore
|
||||
!.gitattributes
|
||||
!.gitignore
|
||||
|
477
Documentation/dev-tools/checkuapi.rst
Normal file
477
Documentation/dev-tools/checkuapi.rst
Normal file
@ -0,0 +1,477 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
============
|
||||
UAPI Checker
|
||||
============
|
||||
|
||||
The UAPI checker (``scripts/check-uapi.sh``) is a shell script which
|
||||
checks UAPI header files for userspace backwards-compatibility across
|
||||
the git tree.
|
||||
|
||||
Options
|
||||
=======
|
||||
|
||||
This section will describe the options with which ``check-uapi.sh``
|
||||
can be run.
|
||||
|
||||
Usage::
|
||||
|
||||
check-uapi.sh [-b BASE_REF] [-p PAST_REF] [-j N] [-l ERROR_LOG] [-i] [-q] [-v]
|
||||
|
||||
Available options::
|
||||
|
||||
-b BASE_REF Base git reference to use for comparison. If unspecified or empty,
|
||||
will use any dirty changes in tree to UAPI files. If there are no
|
||||
dirty changes, HEAD will be used.
|
||||
-p PAST_REF Compare BASE_REF to PAST_REF (e.g. -p v6.1). If unspecified or empty,
|
||||
will use BASE_REF^1. Must be an ancestor of BASE_REF. Only headers
|
||||
that exist on PAST_REF will be checked for compatibility.
|
||||
-j JOBS Number of checks to run in parallel (default: number of CPU cores).
|
||||
-l ERROR_LOG Write error log to file (default: no error log is generated).
|
||||
-i Ignore ambiguous changes that may or may not break UAPI compatibility.
|
||||
-q Quiet operation.
|
||||
-v Verbose operation (print more information about each header being checked).
|
||||
|
||||
Environmental args::
|
||||
|
||||
ABIDIFF Custom path to abidiff binary
|
||||
CC C compiler (default is "gcc")
|
||||
ARCH Target architecture of C compiler (default is host arch)
|
||||
|
||||
Exit codes::
|
||||
|
||||
0) Success
|
||||
1) ABI difference detected
|
||||
2) Prerequisite not met
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
First, let's try making a change to a UAPI header file that obviously
|
||||
won't break userspace::
|
||||
|
||||
cat << 'EOF' | patch -l -p1
|
||||
--- a/include/uapi/linux/acct.h
|
||||
+++ b/include/uapi/linux/acct.h
|
||||
@@ -21,7 +21,9 @@
|
||||
#include <asm/param.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
-/*
|
||||
+#define FOO
|
||||
+
|
||||
+/*
|
||||
* comp_t is a 16-bit "floating" point number with a 3-bit base 8
|
||||
* exponent and a 13-bit fraction.
|
||||
* comp2_t is 24-bit with 5-bit base 2 exponent and 20 bit fraction
|
||||
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
|
||||
EOF
|
||||
|
||||
Now, let's use the script to validate::
|
||||
|
||||
% ./scripts/check-uapi.sh
|
||||
Installing user-facing UAPI headers from dirty tree... OK
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||
All 912 UAPI headers compatible with x86 appear to be backwards compatible
|
||||
|
||||
Let's add another change that *might* break userspace::
|
||||
|
||||
cat << 'EOF' | patch -l -p1
|
||||
--- a/include/uapi/linux/bpf.h
|
||||
+++ b/include/uapi/linux/bpf.h
|
||||
@@ -74,7 +74,7 @@ struct bpf_insn {
|
||||
__u8 dst_reg:4; /* dest register */
|
||||
__u8 src_reg:4; /* source register */
|
||||
__s16 off; /* signed offset */
|
||||
- __s32 imm; /* signed immediate constant */
|
||||
+ __u32 imm; /* unsigned immediate constant */
|
||||
};
|
||||
|
||||
/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
|
||||
EOF
|
||||
|
||||
The script will catch this::
|
||||
|
||||
% ./scripts/check-uapi.sh
|
||||
Installing user-facing UAPI headers from dirty tree... OK
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||
==== ABI differences detected in include/linux/bpf.h from HEAD -> dirty tree ====
|
||||
[C] 'struct bpf_insn' changed:
|
||||
type size hasn't changed
|
||||
1 data member change:
|
||||
type of '__s32 imm' changed:
|
||||
typedef name changed from __s32 to __u32 at int-ll64.h:27:1
|
||||
underlying type 'int' changed:
|
||||
type name changed from 'int' to 'unsigned int'
|
||||
type size hasn't changed
|
||||
==================================================================================
|
||||
|
||||
error - 1/912 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||
|
||||
In this case, the script is reporting the type change because it could
|
||||
break a userspace program that passes in a negative number. Now, let's
|
||||
say you know that no userspace program could possibly be using a negative
|
||||
value in ``imm``, so changing to an unsigned type there shouldn't hurt
|
||||
anything. You can pass the ``-i`` flag to the script to ignore changes
|
||||
in which the userspace backwards compatibility is ambiguous::
|
||||
|
||||
% ./scripts/check-uapi.sh -i
|
||||
Installing user-facing UAPI headers from dirty tree... OK
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||
All 912 UAPI headers compatible with x86 appear to be backwards compatible
|
||||
|
||||
Now, let's make a similar change that *will* break userspace::
|
||||
|
||||
cat << 'EOF' | patch -l -p1
|
||||
--- a/include/uapi/linux/bpf.h
|
||||
+++ b/include/uapi/linux/bpf.h
|
||||
@@ -71,8 +71,8 @@ enum {
|
||||
|
||||
struct bpf_insn {
|
||||
__u8 code; /* opcode */
|
||||
- __u8 dst_reg:4; /* dest register */
|
||||
__u8 src_reg:4; /* source register */
|
||||
+ __u8 dst_reg:4; /* dest register */
|
||||
__s16 off; /* signed offset */
|
||||
__s32 imm; /* signed immediate constant */
|
||||
};
|
||||
EOF
|
||||
|
||||
Since we're re-ordering an existing struct member, there's no ambiguity,
|
||||
and the script will report the breakage even if you pass ``-i``::
|
||||
|
||||
% ./scripts/check-uapi.sh -i
|
||||
Installing user-facing UAPI headers from dirty tree... OK
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||
==== ABI differences detected in include/linux/bpf.h from HEAD -> dirty tree ====
|
||||
[C] 'struct bpf_insn' changed:
|
||||
type size hasn't changed
|
||||
2 data member changes:
|
||||
'__u8 dst_reg' offset changed from 8 to 12 (in bits) (by +4 bits)
|
||||
'__u8 src_reg' offset changed from 12 to 8 (in bits) (by -4 bits)
|
||||
==================================================================================
|
||||
|
||||
error - 1/912 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||
|
||||
Let's commit the breaking change, then commit the innocuous change::
|
||||
|
||||
% git commit -m 'Breaking UAPI change' include/uapi/linux/bpf.h
|
||||
[detached HEAD f758e574663a] Breaking UAPI change
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
% git commit -m 'Innocuous UAPI change' include/uapi/linux/acct.h
|
||||
[detached HEAD 2e87df769081] Innocuous UAPI change
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
Now, let's run the script again with no arguments::
|
||||
|
||||
% ./scripts/check-uapi.sh
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Installing user-facing UAPI headers from HEAD^1... OK
|
||||
Checking changes to UAPI headers between HEAD^1 and HEAD...
|
||||
All 912 UAPI headers compatible with x86 appear to be backwards compatible
|
||||
|
||||
It doesn't catch any breaking change because, by default, it only
|
||||
compares ``HEAD`` to ``HEAD^1``. The breaking change was committed on
|
||||
``HEAD~2``. If we wanted the search scope to go back further, we'd have to
|
||||
use the ``-p`` option to pass a different past reference. In this case,
|
||||
let's pass ``-p HEAD~2`` to the script so it checks UAPI changes between
|
||||
``HEAD~2`` and ``HEAD``::
|
||||
|
||||
% ./scripts/check-uapi.sh -p HEAD~2
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Installing user-facing UAPI headers from HEAD~2... OK
|
||||
Checking changes to UAPI headers between HEAD~2 and HEAD...
|
||||
==== ABI differences detected in include/linux/bpf.h from HEAD~2 -> HEAD ====
|
||||
[C] 'struct bpf_insn' changed:
|
||||
type size hasn't changed
|
||||
2 data member changes:
|
||||
'__u8 dst_reg' offset changed from 8 to 12 (in bits) (by +4 bits)
|
||||
'__u8 src_reg' offset changed from 12 to 8 (in bits) (by -4 bits)
|
||||
==============================================================================
|
||||
|
||||
error - 1/912 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||
|
||||
Alternatively, we could have also run with ``-b HEAD~``. This would set the
|
||||
base reference to ``HEAD~`` so then the script would compare it to ``HEAD~^1``.
|
||||
|
||||
Architecture-specific Headers
|
||||
-----------------------------
|
||||
|
||||
Consider this change::
|
||||
|
||||
cat << 'EOF' | patch -l -p1
|
||||
--- a/arch/arm64/include/uapi/asm/sigcontext.h
|
||||
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
|
||||
@@ -70,6 +70,7 @@ struct sigcontext {
|
||||
struct _aarch64_ctx {
|
||||
__u32 magic;
|
||||
__u32 size;
|
||||
+ __u32 new_var;
|
||||
};
|
||||
|
||||
#define FPSIMD_MAGIC 0x46508001
|
||||
EOF
|
||||
|
||||
This is a change to an arm64-specific UAPI header file. In this example, I'm
|
||||
running the script from an x86 machine with an x86 compiler, so, by default,
|
||||
the script only checks x86-compatible UAPI header files::
|
||||
|
||||
% ./scripts/check-uapi.sh
|
||||
Installing user-facing UAPI headers from dirty tree... OK
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
No changes to UAPI headers were applied between HEAD and dirty tree
|
||||
|
||||
With an x86 compiler, we can't check header files in ``arch/arm64``, so the
|
||||
script doesn't even try.
|
||||
|
||||
If we want to check the header file, we'll have to use an arm64 compiler and
|
||||
set ``ARCH`` accordingly::
|
||||
|
||||
% CC=aarch64-linux-gnu-gcc ARCH=arm64 ./scripts/check-uapi.sh
|
||||
Installing user-facing UAPI headers from dirty tree... OK
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||
==== ABI differences detected in include/asm/sigcontext.h from HEAD -> dirty tree ====
|
||||
[C] 'struct _aarch64_ctx' changed:
|
||||
type size changed from 64 to 96 (in bits)
|
||||
1 data member insertion:
|
||||
'__u32 new_var', at offset 64 (in bits) at sigcontext.h:73:1
|
||||
-- snip --
|
||||
[C] 'struct zt_context' changed:
|
||||
type size changed from 128 to 160 (in bits)
|
||||
2 data member changes (1 filtered):
|
||||
'__u16 nregs' offset changed from 64 to 96 (in bits) (by +32 bits)
|
||||
'__u16 __reserved[3]' offset changed from 80 to 112 (in bits) (by +32 bits)
|
||||
=======================================================================================
|
||||
|
||||
error - 1/884 UAPI headers compatible with arm64 appear _not_ to be backwards compatible
|
||||
|
||||
We can see with ``ARCH`` and ``CC`` set properly for the file, the ABI
|
||||
change is reported properly. Also notice that the total number of UAPI
|
||||
header files checked by the script changes. This is because the number
|
||||
of headers installed for arm64 platforms is different than x86.
|
||||
|
||||
Cross-Dependency Breakages
|
||||
--------------------------
|
||||
|
||||
Consider this change::
|
||||
|
||||
cat << 'EOF' | patch -l -p1
|
||||
--- a/include/uapi/linux/types.h
|
||||
+++ b/include/uapi/linux/types.h
|
||||
@@ -52,7 +52,7 @@ typedef __u32 __bitwise __wsum;
|
||||
#define __aligned_be64 __be64 __attribute__((aligned(8)))
|
||||
#define __aligned_le64 __le64 __attribute__((aligned(8)))
|
||||
|
||||
-typedef unsigned __bitwise __poll_t;
|
||||
+typedef unsigned short __bitwise __poll_t;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _UAPI_LINUX_TYPES_H */
|
||||
EOF
|
||||
|
||||
Here, we're changing a ``typedef`` in ``types.h``. This doesn't break
|
||||
a UAPI in ``types.h``, but other UAPIs in the tree may break due to
|
||||
this change::
|
||||
|
||||
% ./scripts/check-uapi.sh
|
||||
Installing user-facing UAPI headers from dirty tree... OK
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||
==== ABI differences detected in include/linux/eventpoll.h from HEAD -> dirty tree ====
|
||||
[C] 'struct epoll_event' changed:
|
||||
type size changed from 96 to 80 (in bits)
|
||||
2 data member changes:
|
||||
type of '__poll_t events' changed:
|
||||
underlying type 'unsigned int' changed:
|
||||
type name changed from 'unsigned int' to 'unsigned short int'
|
||||
type size changed from 32 to 16 (in bits)
|
||||
'__u64 data' offset changed from 32 to 16 (in bits) (by -16 bits)
|
||||
========================================================================================
|
||||
include/linux/eventpoll.h did not change between HEAD and dirty tree...
|
||||
It's possible a change to one of the headers it includes caused this error:
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
Note that the script noticed the failing header file did not change,
|
||||
so it assumes one of its includes must have caused the breakage. Indeed,
|
||||
we can see ``linux/types.h`` is used from ``eventpoll.h``.
|
||||
|
||||
UAPI Header Removals
|
||||
--------------------
|
||||
|
||||
Consider this change::
|
||||
|
||||
cat << 'EOF' | patch -l -p1
|
||||
diff --git a/include/uapi/asm-generic/Kbuild b/include/uapi/asm-generic/Kbuild
|
||||
index ebb180aac74e..a9c88b0a8b3b 100644
|
||||
--- a/include/uapi/asm-generic/Kbuild
|
||||
+++ b/include/uapi/asm-generic/Kbuild
|
||||
@@ -31,6 +31,6 @@ mandatory-y += stat.h
|
||||
mandatory-y += statfs.h
|
||||
mandatory-y += swab.h
|
||||
mandatory-y += termbits.h
|
||||
-mandatory-y += termios.h
|
||||
+#mandatory-y += termios.h
|
||||
mandatory-y += types.h
|
||||
mandatory-y += unistd.h
|
||||
EOF
|
||||
|
||||
This script removes a UAPI header file from the install list. Let's run
|
||||
the script::
|
||||
|
||||
% ./scripts/check-uapi.sh
|
||||
Installing user-facing UAPI headers from dirty tree... OK
|
||||
Installing user-facing UAPI headers from HEAD... OK
|
||||
Checking changes to UAPI headers between HEAD and dirty tree...
|
||||
==== UAPI header include/asm/termios.h was removed between HEAD and dirty tree ====
|
||||
|
||||
error - 1/912 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||
|
||||
Removing a UAPI header is considered a breaking change, and the script
|
||||
will flag it as such.
|
||||
|
||||
Checking Historic UAPI Compatibility
|
||||
------------------------------------
|
||||
|
||||
You can use the ``-b`` and ``-p`` options to examine different chunks of your
|
||||
git tree. For example, to check all changed UAPI header files between tags
|
||||
v6.0 and v6.1, you'd run::
|
||||
|
||||
% ./scripts/check-uapi.sh -b v6.1 -p v6.0
|
||||
Installing user-facing UAPI headers from v6.1... OK
|
||||
Installing user-facing UAPI headers from v6.0... OK
|
||||
Checking changes to UAPI headers between v6.0 and v6.1...
|
||||
|
||||
--- snip ---
|
||||
error - 37/907 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||
|
||||
Note: Before v5.3, a header file needed by the script is not present,
|
||||
so the script is unable to check changes before then.
|
||||
|
||||
You'll notice that the script detected many UAPI changes that are not
|
||||
backwards compatible. Knowing that kernel UAPIs are supposed to be stable
|
||||
forever, this is an alarming result. This brings us to the next section:
|
||||
caveats.
|
||||
|
||||
Caveats
|
||||
=======
|
||||
|
||||
The UAPI checker makes no assumptions about the author's intention, so some
|
||||
types of changes may be flagged even though they intentionally break UAPI.
|
||||
|
||||
Removals For Refactoring or Deprecation
|
||||
---------------------------------------
|
||||
|
||||
Sometimes drivers for very old hardware are removed, such as in this example::
|
||||
|
||||
% ./scripts/check-uapi.sh -b ba47652ba655
|
||||
Installing user-facing UAPI headers from ba47652ba655... OK
|
||||
Installing user-facing UAPI headers from ba47652ba655^1... OK
|
||||
Checking changes to UAPI headers between ba47652ba655^1 and ba47652ba655...
|
||||
==== UAPI header include/linux/meye.h was removed between ba47652ba655^1 and ba47652ba655 ====
|
||||
|
||||
error - 1/910 UAPI headers compatible with x86 appear _not_ to be backwards compatible
|
||||
|
||||
The script will always flag removals (even if they're intentional).
|
||||
|
||||
Struct Expansions
|
||||
-----------------
|
||||
|
||||
Depending on how a structure is handled in kernelspace, a change which
|
||||
expands a struct could be non-breaking.
|
||||
|
||||
If a struct is used as the argument to an ioctl, then the kernel driver
|
||||
must be able to handle ioctl commands of any size. Beyond that, you need
|
||||
to be careful when copying data from the user. Say, for example, that
|
||||
``struct foo`` is changed like this::
|
||||
|
||||
struct foo {
|
||||
__u64 a; /* added in version 1 */
|
||||
+ __u32 b; /* added in version 2 */
|
||||
+ __u32 c; /* added in version 2 */
|
||||
}
|
||||
|
||||
By default, the script will flag this kind of change for further review::
|
||||
|
||||
[C] 'struct foo' changed:
|
||||
type size changed from 64 to 128 (in bits)
|
||||
2 data member insertions:
|
||||
'__u32 b', at offset 64 (in bits)
|
||||
'__u32 c', at offset 96 (in bits)
|
||||
|
||||
However, it is possible that this change was made safely.
|
||||
|
||||
If a userspace program was built with version 1, it will think
|
||||
``sizeof(struct foo)`` is 8. That size will be encoded in the
|
||||
ioctl value that gets sent to the kernel. If the kernel is built
|
||||
with version 2, it will think the ``sizeof(struct foo)`` is 16.
|
||||
|
||||
The kernel can use the ``_IOC_SIZE`` macro to get the size encoded
|
||||
in the ioctl code that the user passed in and then use
|
||||
``copy_struct_from_user()`` to safely copy the value::
|
||||
|
||||
int handle_ioctl(unsigned long cmd, unsigned long arg)
|
||||
{
|
||||
switch _IOC_NR(cmd) {
|
||||
0x01: {
|
||||
struct foo my_cmd; /* size 16 in the kernel */
|
||||
|
||||
ret = copy_struct_from_user(&my_cmd, arg, sizeof(struct foo), _IOC_SIZE(cmd));
|
||||
...
|
||||
|
||||
``copy_struct_from_user`` will zero the struct in the kernel and then copy
|
||||
only the bytes passed in from the user (leaving new members zeroized).
|
||||
If the user passed in a larger struct, the extra members are ignored.
|
||||
|
||||
If you know this situation is accounted for in the kernel code, you can
|
||||
pass ``-i`` to the script, and struct expansions like this will be ignored.
|
||||
|
||||
Flex Array Migration
|
||||
--------------------
|
||||
|
||||
While the script handles expansion into an existing flex array, it does
|
||||
still flag initial migration to flex arrays from 1-element fake flex
|
||||
arrays. For example::
|
||||
|
||||
struct foo {
|
||||
__u32 x;
|
||||
- __u32 flex[1]; /* fake flex */
|
||||
+ __u32 flex[]; /* real flex */
|
||||
};
|
||||
|
||||
This change would be flagged by the script::
|
||||
|
||||
[C] 'struct foo' changed:
|
||||
type size changed from 64 to 32 (in bits)
|
||||
1 data member change:
|
||||
type of '__u32 flex[1]' changed:
|
||||
type name changed from '__u32[1]' to '__u32[]'
|
||||
array type size changed from 32 to 'unknown'
|
||||
array type subrange 1 changed length from 1 to 'unknown'
|
||||
|
||||
At this time, there's no way to filter these types of changes, so be
|
||||
aware of this possible false positive.
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
While many types of false positives are filtered out by the script,
|
||||
it's possible there are some cases where the script flags a change
|
||||
which does not break UAPI. It's also possible a change which *does*
|
||||
break userspace would not be flagged by this script. While the script
|
||||
has been run on much of the kernel history, there could still be corner
|
||||
cases that are not accounted for.
|
||||
|
||||
The intention is for this script to be used as a quick check for
|
||||
maintainers or automated tooling, not as the end-all authority on
|
||||
patch compatibility. It's best to remember: use your best judgment
|
||||
(and ideally a unit test in userspace) to make sure your UAPI changes
|
||||
are backwards-compatible!
|
@ -31,6 +31,7 @@ Documentation/dev-tools/testing-overview.rst
|
||||
kselftest
|
||||
kunit/index
|
||||
ktap
|
||||
checkuapi
|
||||
|
||||
|
||||
.. only:: subproject and html
|
||||
|
@ -66,6 +66,10 @@ for aligning variables/macros, for reflowing text and other similar tasks.
|
||||
See the file :ref:`Documentation/process/clang-format.rst <clangformat>`
|
||||
for more details.
|
||||
|
||||
Some basic editor settings, such as indentation and line endings, will be
|
||||
set automatically if you are using an editor that is compatible with
|
||||
EditorConfig. See the official EditorConfig website for more information:
|
||||
https://editorconfig.org/
|
||||
|
||||
Abstraction layers
|
||||
******************
|
||||
|
@ -735,6 +735,10 @@ for aligning variables/macros, for reflowing text and other similar tasks.
|
||||
See the file :ref:`Documentation/process/clang-format.rst <clangformat>`
|
||||
for more details.
|
||||
|
||||
Some basic editor settings, such as indentation and line endings, will be
|
||||
set automatically if you are using an editor that is compatible with
|
||||
EditorConfig. See the official EditorConfig website for more information:
|
||||
https://editorconfig.org/
|
||||
|
||||
10) Kconfig configuration files
|
||||
-------------------------------
|
||||
|
23
Makefile
23
Makefile
@ -155,6 +155,15 @@ endif
|
||||
|
||||
export KBUILD_EXTMOD
|
||||
|
||||
# backward compatibility
|
||||
KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)
|
||||
|
||||
ifeq ("$(origin W)", "command line")
|
||||
KBUILD_EXTRA_WARN := $(W)
|
||||
endif
|
||||
|
||||
export KBUILD_EXTRA_WARN
|
||||
|
||||
# Kbuild will save output files in the current working directory.
|
||||
# This does not need to match to the root of the kernel source tree.
|
||||
#
|
||||
@ -181,14 +190,11 @@ ifeq ("$(origin O)", "command line")
|
||||
endif
|
||||
|
||||
ifneq ($(KBUILD_OUTPUT),)
|
||||
# Make's built-in functions such as $(abspath ...), $(realpath ...) cannot
|
||||
# expand a shell special character '~'. We use a somewhat tedious way here.
|
||||
abs_objtree := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) && pwd)
|
||||
$(if $(abs_objtree),, \
|
||||
$(error failed to create output directory "$(KBUILD_OUTPUT)"))
|
||||
|
||||
# $(realpath ...) gets empty if the path does not exist. Run 'mkdir -p' first.
|
||||
$(shell mkdir -p "$(KBUILD_OUTPUT)")
|
||||
# $(realpath ...) resolves symlinks
|
||||
abs_objtree := $(realpath $(abs_objtree))
|
||||
abs_objtree := $(realpath $(KBUILD_OUTPUT))
|
||||
$(if $(abs_objtree),,$(error failed to create output directory "$(KBUILD_OUTPUT)"))
|
||||
endif # ifneq ($(KBUILD_OUTPUT),)
|
||||
|
||||
ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
|
||||
@ -609,8 +615,6 @@ export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL KBUILD_RUSTFLAGS_KERNEL
|
||||
export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o \
|
||||
-name CVS -o -name .pc -o -name .hg -o -name .git \) \
|
||||
-prune -o
|
||||
export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
|
||||
--exclude CVS --exclude .pc --exclude .hg --exclude .git
|
||||
|
||||
# ===========================================================================
|
||||
# Rules shared between *config targets and build targets
|
||||
@ -1662,6 +1666,7 @@ help:
|
||||
@echo ' 1: warnings which may be relevant and do not occur too often'
|
||||
@echo ' 2: warnings which occur quite often but may still be relevant'
|
||||
@echo ' 3: more obscure warnings, can most likely be ignored'
|
||||
@echo ' c: extra checks in the configuration stage (Kconfig)'
|
||||
@echo ' e: warnings are being treated as errors'
|
||||
@echo ' Multiple levels can be combined with W=12 or W=123'
|
||||
@$(if $(dtstree), \
|
||||
|
@ -3,9 +3,6 @@
|
||||
# Building vDSO images for sparc.
|
||||
#
|
||||
|
||||
VDSO64-$(CONFIG_SPARC64) := y
|
||||
VDSOCOMPAT-$(CONFIG_COMPAT) := y
|
||||
|
||||
# files to link into the vdso
|
||||
vobjs-y := vdso-note.o vclock_gettime.o
|
||||
|
||||
@ -13,22 +10,15 @@ vobjs-y := vdso-note.o vclock_gettime.o
|
||||
obj-y += vma.o
|
||||
|
||||
# vDSO images to build
|
||||
vdso_img-$(VDSO64-y) += 64
|
||||
vdso_img-$(VDSOCOMPAT-y) += 32
|
||||
obj-$(CONFIG_SPARC64) += vdso-image-64.o
|
||||
obj-$(CONFIG_COMPAT) += vdso-image-32.o
|
||||
|
||||
vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
|
||||
vobjs := $(addprefix $(obj)/, $(vobjs-y))
|
||||
|
||||
$(obj)/vdso.o: $(obj)/vdso.so
|
||||
|
||||
targets += vdso.lds $(vobjs-y)
|
||||
|
||||
# Build the vDSO image C files and link them in.
|
||||
vdso_img_objs := $(vdso_img-y:%=vdso-image-%.o)
|
||||
vdso_img_cfiles := $(vdso_img-y:%=vdso-image-%.c)
|
||||
vdso_img_sodbg := $(vdso_img-y:%=vdso%.so.dbg)
|
||||
obj-y += $(vdso_img_objs)
|
||||
targets += $(vdso_img_cfiles)
|
||||
targets += $(vdso_img_sodbg) $(vdso_img-y:%=vdso%.so)
|
||||
targets += $(foreach x, 32 64, vdso-image-$(x).c vdso$(x).so vdso$(x).so.dbg)
|
||||
|
||||
CPPFLAGS_vdso.lds += -P -C
|
||||
|
||||
|
@ -6,15 +6,6 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/stringify.h>
|
||||
|
||||
/*
|
||||
* Export symbols from the kernel to modules. Forked from module.h
|
||||
* to reduce the amount of pointless cruft we feed to gcc when only
|
||||
* exporting a simple symbol or two.
|
||||
*
|
||||
* Try not to add #includes here. It slows compilation and makes kernel
|
||||
* hackers place grumpy comments in header files.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This comment block is used by fixdep. Please do not remove.
|
||||
*
|
||||
@ -23,15 +14,6 @@
|
||||
* side effect of the *.o build rule.
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef MODULE
|
||||
extern struct module __this_module;
|
||||
#define THIS_MODULE (&__this_module)
|
||||
#else
|
||||
#define THIS_MODULE ((struct module *)0)
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define __EXPORT_SYMBOL_REF(sym) \
|
||||
.balign 8 ASM_NL \
|
||||
|
@ -179,6 +179,13 @@ extern void (*late_time_init)(void);
|
||||
|
||||
extern bool initcall_debug;
|
||||
|
||||
#ifdef MODULE
|
||||
extern struct module __this_module;
|
||||
#define THIS_MODULE (&__this_module)
|
||||
#else
|
||||
#define THIS_MODULE ((struct module *)0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MODULE
|
||||
|
@ -82,15 +82,6 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init)
|
||||
# Warn if there is an enum types mismatch
|
||||
KBUILD_CFLAGS += $(call cc-option,-Wenum-conversion)
|
||||
|
||||
# backward compatibility
|
||||
KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)
|
||||
|
||||
ifeq ("$(origin W)", "command line")
|
||||
KBUILD_EXTRA_WARN := $(W)
|
||||
endif
|
||||
|
||||
export KBUILD_EXTRA_WARN
|
||||
|
||||
#
|
||||
# W=1 - warnings which may be relevant and do not occur too often
|
||||
#
|
||||
|
@ -83,8 +83,8 @@ dtb-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
|
||||
multi-dtb-y := $(call multi-search, $(dtb-y), .dtb, -dtbs)
|
||||
# Primitive DTB compiled from *.dts
|
||||
real-dtb-y := $(call real-search, $(dtb-y), .dtb, -dtbs)
|
||||
# Base DTB that overlay is applied onto (each first word of $(*-dtbs) expansion)
|
||||
base-dtb-y := $(foreach m, $(multi-dtb-y), $(firstword $(call suffix-search, $m, .dtb, -dtbs)))
|
||||
# Base DTB that overlay is applied onto
|
||||
base-dtb-y := $(filter %.dtb, $(call real-search, $(multi-dtb-y), .dtb, -dtbs))
|
||||
|
||||
always-y += $(dtb-y)
|
||||
|
||||
|
@ -4,27 +4,6 @@
|
||||
include $(srctree)/scripts/Kbuild.include
|
||||
include $(srctree)/scripts/Makefile.lib
|
||||
|
||||
KERNELPATH := kernel-$(subst -,_,$(KERNELRELEASE))
|
||||
# Include only those top-level files that are needed by make, plus the GPL copy
|
||||
TAR_CONTENT := Documentation LICENSES arch block certs crypto drivers fs \
|
||||
include init io_uring ipc kernel lib mm net rust \
|
||||
samples scripts security sound tools usr virt \
|
||||
.config Makefile \
|
||||
Kbuild Kconfig COPYING $(wildcard localversion*)
|
||||
|
||||
quiet_cmd_src_tar = TAR $(2).tar.gz
|
||||
cmd_src_tar = \
|
||||
if test "$(objtree)" != "$(srctree)"; then \
|
||||
echo >&2; \
|
||||
echo >&2 " ERROR:"; \
|
||||
echo >&2 " Building source tarball is not possible outside the"; \
|
||||
echo >&2 " kernel source tree. Don't set KBUILD_OUTPUT"; \
|
||||
echo >&2; \
|
||||
false; \
|
||||
fi ; \
|
||||
tar -I $(KGZIP) -c $(RCS_TAR_IGNORE) -f $(2).tar.gz \
|
||||
--transform 's:^:$(2)/:S' $(TAR_CONTENT) $(3)
|
||||
|
||||
# Git
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@ -130,8 +109,6 @@ debian-orig: linux.tar$(debian-orig-suffix) debian
|
||||
cp $< ../$(orig-name); \
|
||||
fi
|
||||
|
||||
KBUILD_PKG_ROOTCMD ?= 'fakeroot -u'
|
||||
|
||||
PHONY += deb-pkg srcdeb-pkg bindeb-pkg
|
||||
|
||||
deb-pkg: private build-type := source,binary
|
||||
@ -146,7 +123,7 @@ deb-pkg srcdeb-pkg bindeb-pkg:
|
||||
$(if $(findstring source, $(build-type)), \
|
||||
--unsigned-source --compression=$(KDEB_SOURCE_COMPRESS)) \
|
||||
$(if $(findstring binary, $(build-type)), \
|
||||
--rules-file='$(MAKE) -f debian/rules' --jobs=1 -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch), \
|
||||
-R'$(MAKE) -f debian/rules' -j1 -a$$(cat debian/arch), \
|
||||
--no-check-builddeps) \
|
||||
$(DPKG_FLAGS))
|
||||
|
||||
@ -157,9 +134,8 @@ snap-pkg:
|
||||
rm -rf $(objtree)/snap
|
||||
mkdir $(objtree)/snap
|
||||
$(MAKE) clean
|
||||
$(call cmd,src_tar,$(KERNELPATH))
|
||||
sed "s@KERNELRELEASE@$(KERNELRELEASE)@; \
|
||||
s@SRCTREE@$(shell realpath $(KERNELPATH).tar.gz)@" \
|
||||
s@SRCTREE@$(abs_srctree)@" \
|
||||
$(srctree)/scripts/package/snapcraft.template > \
|
||||
$(objtree)/snap/snapcraft.yaml
|
||||
cd $(objtree)/snap && \
|
||||
|
573
scripts/check-uapi.sh
Executable file
573
scripts/check-uapi.sh
Executable file
@ -0,0 +1,573 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Script to check commits for UAPI backwards compatibility
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
print_usage() {
|
||||
name=$(basename "$0")
|
||||
cat << EOF
|
||||
$name - check for UAPI header stability across Git commits
|
||||
|
||||
By default, the script will check to make sure the latest commit (or current
|
||||
dirty changes) did not introduce ABI changes when compared to HEAD^1. You can
|
||||
check against additional commit ranges with the -b and -p options.
|
||||
|
||||
The script will not check UAPI headers for architectures other than the one
|
||||
defined in ARCH.
|
||||
|
||||
Usage: $name [-b BASE_REF] [-p PAST_REF] [-j N] [-l ERROR_LOG] [-i] [-q] [-v]
|
||||
|
||||
Options:
|
||||
-b BASE_REF Base git reference to use for comparison. If unspecified or empty,
|
||||
will use any dirty changes in tree to UAPI files. If there are no
|
||||
dirty changes, HEAD will be used.
|
||||
-p PAST_REF Compare BASE_REF to PAST_REF (e.g. -p v6.1). If unspecified or empty,
|
||||
will use BASE_REF^1. Must be an ancestor of BASE_REF. Only headers
|
||||
that exist on PAST_REF will be checked for compatibility.
|
||||
-j JOBS Number of checks to run in parallel (default: number of CPU cores).
|
||||
-l ERROR_LOG Write error log to file (default: no error log is generated).
|
||||
-i Ignore ambiguous changes that may or may not break UAPI compatibility.
|
||||
-q Quiet operation.
|
||||
-v Verbose operation (print more information about each header being checked).
|
||||
|
||||
Environmental args:
|
||||
ABIDIFF Custom path to abidiff binary
|
||||
CC C compiler (default is "gcc")
|
||||
ARCH Target architecture for the UAPI check (default is host arch)
|
||||
|
||||
Exit codes:
|
||||
$SUCCESS) Success
|
||||
$FAIL_ABI) ABI difference detected
|
||||
$FAIL_PREREQ) Prerequisite not met
|
||||
EOF
|
||||
}
|
||||
|
||||
readonly SUCCESS=0
|
||||
readonly FAIL_ABI=1
|
||||
readonly FAIL_PREREQ=2
|
||||
|
||||
# Print to stderr
|
||||
eprintf() {
|
||||
# shellcheck disable=SC2059
|
||||
printf "$@" >&2
|
||||
}
|
||||
|
||||
# Expand an array with a specific character (similar to Python string.join())
|
||||
join() {
|
||||
local IFS="$1"
|
||||
shift
|
||||
printf "%s" "$*"
|
||||
}
|
||||
|
||||
# Create abidiff suppressions
|
||||
gen_suppressions() {
|
||||
# Common enum variant names which we don't want to worry about
|
||||
# being shifted when new variants are added.
|
||||
local -a enum_regex=(
|
||||
".*_AFTER_LAST$"
|
||||
".*_CNT$"
|
||||
".*_COUNT$"
|
||||
".*_END$"
|
||||
".*_LAST$"
|
||||
".*_MASK$"
|
||||
".*_MAX$"
|
||||
".*_MAX_BIT$"
|
||||
".*_MAX_BPF_ATTACH_TYPE$"
|
||||
".*_MAX_ID$"
|
||||
".*_MAX_SHIFT$"
|
||||
".*_NBITS$"
|
||||
".*_NETDEV_NUMHOOKS$"
|
||||
".*_NFT_META_IIFTYPE$"
|
||||
".*_NL80211_ATTR$"
|
||||
".*_NLDEV_NUM_OPS$"
|
||||
".*_NUM$"
|
||||
".*_NUM_ELEMS$"
|
||||
".*_NUM_IRQS$"
|
||||
".*_SIZE$"
|
||||
".*_TLSMAX$"
|
||||
"^MAX_.*"
|
||||
"^NUM_.*"
|
||||
)
|
||||
|
||||
# Common padding field names which can be expanded into
|
||||
# without worrying about users.
|
||||
local -a padding_regex=(
|
||||
".*end$"
|
||||
".*pad$"
|
||||
".*pad[0-9]?$"
|
||||
".*pad_[0-9]?$"
|
||||
".*padding$"
|
||||
".*padding[0-9]?$"
|
||||
".*padding_[0-9]?$"
|
||||
".*res$"
|
||||
".*resv$"
|
||||
".*resv[0-9]?$"
|
||||
".*resv_[0-9]?$"
|
||||
".*reserved$"
|
||||
".*reserved[0-9]?$"
|
||||
".*reserved_[0-9]?$"
|
||||
".*rsvd[0-9]?$"
|
||||
".*unused$"
|
||||
)
|
||||
|
||||
cat << EOF
|
||||
[suppress_type]
|
||||
type_kind = enum
|
||||
changed_enumerators_regexp = $(join , "${enum_regex[@]}")
|
||||
EOF
|
||||
|
||||
for p in "${padding_regex[@]}"; do
|
||||
cat << EOF
|
||||
[suppress_type]
|
||||
type_kind = struct
|
||||
has_data_member_inserted_at = offset_of_first_data_member_regexp(${p})
|
||||
EOF
|
||||
done
|
||||
|
||||
if [ "$IGNORE_AMBIGUOUS_CHANGES" = "true" ]; then
|
||||
cat << EOF
|
||||
[suppress_type]
|
||||
type_kind = struct
|
||||
has_data_member_inserted_at = end
|
||||
has_size_change = yes
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if git tree is dirty
|
||||
tree_is_dirty() {
|
||||
! git diff --quiet
|
||||
}
|
||||
|
||||
# Get list of files installed in $ref
|
||||
get_file_list() {
|
||||
local -r ref="$1"
|
||||
local -r tree="$(get_header_tree "$ref")"
|
||||
|
||||
# Print all installed headers, filtering out ones that can't be compiled
|
||||
find "$tree" -type f -name '*.h' -printf '%P\n' | grep -v -f "$INCOMPAT_LIST"
|
||||
}
|
||||
|
||||
# Add to the list of incompatible headers
|
||||
add_to_incompat_list() {
|
||||
local -r ref="$1"
|
||||
|
||||
# Start with the usr/include/Makefile to get a list of the headers
|
||||
# that don't compile using this method.
|
||||
if [ ! -f usr/include/Makefile ]; then
|
||||
eprintf "error - no usr/include/Makefile present at %s\n" "$ref"
|
||||
eprintf "Note: usr/include/Makefile was added in the v5.3 kernel release\n"
|
||||
exit "$FAIL_PREREQ"
|
||||
fi
|
||||
{
|
||||
# shellcheck disable=SC2016
|
||||
printf 'all: ; @echo $(no-header-test)\n'
|
||||
cat usr/include/Makefile
|
||||
} | SRCARCH="$ARCH" make --always-make -f - | tr " " "\n" \
|
||||
| grep -v "asm-generic" >> "$INCOMPAT_LIST"
|
||||
|
||||
# The makefile also skips all asm-generic files, but prints "asm-generic/%"
|
||||
# which won't work for our grep match. Instead, print something grep will match.
|
||||
printf "asm-generic/.*\.h\n" >> "$INCOMPAT_LIST"
|
||||
}
|
||||
|
||||
# Compile the simple test app
|
||||
do_compile() {
|
||||
local -r inc_dir="$1"
|
||||
local -r header="$2"
|
||||
local -r out="$3"
|
||||
printf "int main(void) { return 0; }\n" | \
|
||||
"$CC" -c \
|
||||
-o "$out" \
|
||||
-x c \
|
||||
-O0 \
|
||||
-std=c90 \
|
||||
-fno-eliminate-unused-debug-types \
|
||||
-g \
|
||||
"-I${inc_dir}" \
|
||||
-include "$header" \
|
||||
-
|
||||
}
|
||||
|
||||
# Run make headers_install
|
||||
run_make_headers_install() {
|
||||
local -r ref="$1"
|
||||
local -r install_dir="$(get_header_tree "$ref")"
|
||||
make -j "$MAX_THREADS" ARCH="$ARCH" INSTALL_HDR_PATH="$install_dir" \
|
||||
headers_install > /dev/null
|
||||
}
|
||||
|
||||
# Install headers for both git refs
|
||||
install_headers() {
|
||||
local -r base_ref="$1"
|
||||
local -r past_ref="$2"
|
||||
|
||||
for ref in "$base_ref" "$past_ref"; do
|
||||
printf "Installing user-facing UAPI headers from %s... " "${ref:-dirty tree}"
|
||||
if [ -n "$ref" ]; then
|
||||
git archive --format=tar --prefix="${ref}-archive/" "$ref" \
|
||||
| (cd "$TMP_DIR" && tar xf -)
|
||||
(
|
||||
cd "${TMP_DIR}/${ref}-archive"
|
||||
run_make_headers_install "$ref"
|
||||
add_to_incompat_list "$ref" "$INCOMPAT_LIST"
|
||||
)
|
||||
else
|
||||
run_make_headers_install "$ref"
|
||||
add_to_incompat_list "$ref" "$INCOMPAT_LIST"
|
||||
fi
|
||||
printf "OK\n"
|
||||
done
|
||||
sort -u -o "$INCOMPAT_LIST" "$INCOMPAT_LIST"
|
||||
sed -i -e '/^$/d' "$INCOMPAT_LIST"
|
||||
}
|
||||
|
||||
# Print the path to the headers_install tree for a given ref
|
||||
get_header_tree() {
|
||||
local -r ref="$1"
|
||||
printf "%s" "${TMP_DIR}/${ref}/usr"
|
||||
}
|
||||
|
||||
# Check file list for UAPI compatibility
|
||||
check_uapi_files() {
|
||||
local -r base_ref="$1"
|
||||
local -r past_ref="$2"
|
||||
local -r abi_error_log="$3"
|
||||
|
||||
local passed=0;
|
||||
local failed=0;
|
||||
local -a threads=()
|
||||
set -o errexit
|
||||
|
||||
printf "Checking changes to UAPI headers between %s and %s...\n" "$past_ref" "${base_ref:-dirty tree}"
|
||||
# Loop over all UAPI headers that were installed by $past_ref (if they only exist on $base_ref,
|
||||
# there's no way they're broken and no way to compare anyway)
|
||||
while read -r file; do
|
||||
if [ "${#threads[@]}" -ge "$MAX_THREADS" ]; then
|
||||
if wait "${threads[0]}"; then
|
||||
passed=$((passed + 1))
|
||||
else
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
threads=("${threads[@]:1}")
|
||||
fi
|
||||
|
||||
check_individual_file "$base_ref" "$past_ref" "$file" &
|
||||
threads+=("$!")
|
||||
done < <(get_file_list "$past_ref")
|
||||
|
||||
for t in "${threads[@]}"; do
|
||||
if wait "$t"; then
|
||||
passed=$((passed + 1))
|
||||
else
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$abi_error_log" ]; then
|
||||
printf 'Generated by "%s %s" from git ref %s\n\n' \
|
||||
"$0" "$*" "$(git rev-parse HEAD)" > "$abi_error_log"
|
||||
fi
|
||||
|
||||
while read -r error_file; do
|
||||
{
|
||||
cat "$error_file"
|
||||
printf "\n\n"
|
||||
} | tee -a "${abi_error_log:-/dev/null}" >&2
|
||||
done < <(find "$TMP_DIR" -type f -name '*.error' | sort)
|
||||
|
||||
total="$((passed + failed))"
|
||||
if [ "$failed" -gt 0 ]; then
|
||||
eprintf "error - %d/%d UAPI headers compatible with %s appear _not_ to be backwards compatible\n" \
|
||||
"$failed" "$total" "$ARCH"
|
||||
if [ -n "$abi_error_log" ]; then
|
||||
eprintf "Failure summary saved to %s\n" "$abi_error_log"
|
||||
fi
|
||||
else
|
||||
printf "All %d UAPI headers compatible with %s appear to be backwards compatible\n" \
|
||||
"$total" "$ARCH"
|
||||
fi
|
||||
|
||||
return "$failed"
|
||||
}
|
||||
|
||||
# Check an individual file for UAPI compatibility
|
||||
check_individual_file() {
|
||||
local -r base_ref="$1"
|
||||
local -r past_ref="$2"
|
||||
local -r file="$3"
|
||||
|
||||
local -r base_header="$(get_header_tree "$base_ref")/${file}"
|
||||
local -r past_header="$(get_header_tree "$past_ref")/${file}"
|
||||
|
||||
if [ ! -f "$base_header" ]; then
|
||||
mkdir -p "$(dirname "$base_header")"
|
||||
printf "==== UAPI header %s was removed between %s and %s ====" \
|
||||
"$file" "$past_ref" "$base_ref" \
|
||||
> "${base_header}.error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
compare_abi "$file" "$base_header" "$past_header" "$base_ref" "$past_ref"
|
||||
}
|
||||
|
||||
# Perform the A/B compilation and compare output ABI
|
||||
compare_abi() {
|
||||
local -r file="$1"
|
||||
local -r base_header="$2"
|
||||
local -r past_header="$3"
|
||||
local -r base_ref="$4"
|
||||
local -r past_ref="$5"
|
||||
local -r log="${TMP_DIR}/log/${file}.log"
|
||||
local -r error_log="${TMP_DIR}/log/${file}.error"
|
||||
|
||||
mkdir -p "$(dirname "$log")"
|
||||
|
||||
if ! do_compile "$(get_header_tree "$base_ref")/include" "$base_header" "${base_header}.bin" 2> "$log"; then
|
||||
{
|
||||
warn_str=$(printf "==== Could not compile version of UAPI header %s at %s ====\n" \
|
||||
"$file" "$base_ref")
|
||||
printf "%s\n" "$warn_str"
|
||||
cat "$log"
|
||||
printf -- "=%.0s" $(seq 0 ${#warn_str})
|
||||
} > "$error_log"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! do_compile "$(get_header_tree "$past_ref")/include" "$past_header" "${past_header}.bin" 2> "$log"; then
|
||||
{
|
||||
warn_str=$(printf "==== Could not compile version of UAPI header %s at %s ====\n" \
|
||||
"$file" "$past_ref")
|
||||
printf "%s\n" "$warn_str"
|
||||
cat "$log"
|
||||
printf -- "=%.0s" $(seq 0 ${#warn_str})
|
||||
} > "$error_log"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local ret=0
|
||||
"$ABIDIFF" --non-reachable-types \
|
||||
--suppressions "$SUPPRESSIONS" \
|
||||
"${past_header}.bin" "${base_header}.bin" > "$log" || ret="$?"
|
||||
if [ "$ret" -eq 0 ]; then
|
||||
if [ "$VERBOSE" = "true" ]; then
|
||||
printf "No ABI differences detected in %s from %s -> %s\n" \
|
||||
"$file" "$past_ref" "$base_ref"
|
||||
fi
|
||||
else
|
||||
# Bits in abidiff's return code can be used to determine the type of error
|
||||
if [ $((ret & 0x2)) -gt 0 ]; then
|
||||
eprintf "error - abidiff did not run properly\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$IGNORE_AMBIGUOUS_CHANGES" = "true" ] && [ "$ret" -eq 4 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If the only changes were additions (not modifications to existing APIs), then
|
||||
# there's no problem. Ignore these diffs.
|
||||
if grep "Unreachable types summary" "$log" | grep -q "0 removed" &&
|
||||
grep "Unreachable types summary" "$log" | grep -q "0 changed"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
{
|
||||
warn_str=$(printf "==== ABI differences detected in %s from %s -> %s ====" \
|
||||
"$file" "$past_ref" "$base_ref")
|
||||
printf "%s\n" "$warn_str"
|
||||
sed -e '/summary:/d' -e '/changed type/d' -e '/^$/d' -e 's/^/ /g' "$log"
|
||||
printf -- "=%.0s" $(seq 0 ${#warn_str})
|
||||
if cmp "$past_header" "$base_header" > /dev/null 2>&1; then
|
||||
printf "\n%s did not change between %s and %s...\n" "$file" "$past_ref" "${base_ref:-dirty tree}"
|
||||
printf "It's possible a change to one of the headers it includes caused this error:\n"
|
||||
grep '^#include' "$base_header"
|
||||
printf "\n"
|
||||
fi
|
||||
} > "$error_log"
|
||||
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check that a minimum software version number is satisfied
|
||||
min_version_is_satisfied() {
|
||||
local -r min_version="$1"
|
||||
local -r version_installed="$2"
|
||||
|
||||
printf "%s\n%s\n" "$min_version" "$version_installed" \
|
||||
| sort -Vc > /dev/null 2>&1
|
||||
}
|
||||
|
||||
# Make sure we have the tools we need and the arguments make sense
|
||||
check_deps() {
|
||||
ABIDIFF="${ABIDIFF:-abidiff}"
|
||||
CC="${CC:-gcc}"
|
||||
ARCH="${ARCH:-$(uname -m)}"
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
ARCH="x86"
|
||||
fi
|
||||
|
||||
local -r abidiff_min_version="2.4"
|
||||
local -r libdw_min_version_if_clang="0.171"
|
||||
|
||||
if ! command -v "$ABIDIFF" > /dev/null 2>&1; then
|
||||
eprintf "error - abidiff not found!\n"
|
||||
eprintf "Please install abigail-tools version %s or greater\n" "$abidiff_min_version"
|
||||
eprintf "See: https://sourceware.org/libabigail/manual/libabigail-overview.html\n"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local -r abidiff_version="$("$ABIDIFF" --version | cut -d ' ' -f 2)"
|
||||
if ! min_version_is_satisfied "$abidiff_min_version" "$abidiff_version"; then
|
||||
eprintf "error - abidiff version too old: %s\n" "$abidiff_version"
|
||||
eprintf "Please install abigail-tools version %s or greater\n" "$abidiff_min_version"
|
||||
eprintf "See: https://sourceware.org/libabigail/manual/libabigail-overview.html\n"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! command -v "$CC" > /dev/null 2>&1; then
|
||||
eprintf 'error - %s not found\n' "$CC"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if "$CC" --version | grep -q clang; then
|
||||
local -r libdw_version="$(ldconfig -v 2>/dev/null | grep -v SKIPPED | grep -m 1 -o 'libdw-[0-9]\+.[0-9]\+' | cut -c 7-)"
|
||||
if ! min_version_is_satisfied "$libdw_min_version_if_clang" "$libdw_version"; then
|
||||
eprintf "error - libdw version too old for use with clang: %s\n" "$libdw_version"
|
||||
eprintf "Please install libdw from elfutils version %s or greater\n" "$libdw_min_version_if_clang"
|
||||
eprintf "See: https://sourceware.org/elfutils/\n"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "arch/${ARCH}" ]; then
|
||||
eprintf 'error - ARCH "%s" is not a subdirectory under arch/\n' "$ARCH"
|
||||
eprintf "Please set ARCH to one of:\n%s\n" "$(find arch -maxdepth 1 -mindepth 1 -type d -printf '%f ' | fmt)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
|
||||
eprintf "error - this script requires the kernel tree to be initialized with Git\n"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! git rev-parse --verify "$past_ref" > /dev/null 2>&1; then
|
||||
printf 'error - invalid git reference "%s"\n' "$past_ref"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -n "$base_ref" ]; then
|
||||
if ! git merge-base --is-ancestor "$past_ref" "$base_ref" > /dev/null 2>&1; then
|
||||
printf 'error - "%s" is not an ancestor of base ref "%s"\n' "$past_ref" "$base_ref"
|
||||
return 1
|
||||
fi
|
||||
if [ "$(git rev-parse "$base_ref")" = "$(git rev-parse "$past_ref")" ]; then
|
||||
printf 'error - "%s" and "%s" are the same reference\n' "$past_ref" "$base_ref"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
run() {
|
||||
local base_ref="$1"
|
||||
local past_ref="$2"
|
||||
local abi_error_log="$3"
|
||||
shift 3
|
||||
|
||||
if [ -z "$KERNEL_SRC" ]; then
|
||||
KERNEL_SRC="$(realpath "$(dirname "$0")"/..)"
|
||||
fi
|
||||
|
||||
cd "$KERNEL_SRC"
|
||||
|
||||
if [ -z "$base_ref" ] && ! tree_is_dirty; then
|
||||
base_ref=HEAD
|
||||
fi
|
||||
|
||||
if [ -z "$past_ref" ]; then
|
||||
if [ -n "$base_ref" ]; then
|
||||
past_ref="${base_ref}^1"
|
||||
else
|
||||
past_ref=HEAD
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! check_deps; then
|
||||
exit "$FAIL_PREREQ"
|
||||
fi
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
readonly TMP_DIR
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
|
||||
readonly INCOMPAT_LIST="${TMP_DIR}/incompat_list.txt"
|
||||
touch "$INCOMPAT_LIST"
|
||||
|
||||
readonly SUPPRESSIONS="${TMP_DIR}/suppressions.txt"
|
||||
gen_suppressions > "$SUPPRESSIONS"
|
||||
|
||||
# Run make install_headers for both refs
|
||||
install_headers "$base_ref" "$past_ref"
|
||||
|
||||
# Check for any differences in the installed header trees
|
||||
if diff -r -q "$(get_header_tree "$base_ref")" "$(get_header_tree "$past_ref")" > /dev/null 2>&1; then
|
||||
printf "No changes to UAPI headers were applied between %s and %s\n" "$past_ref" "${base_ref:-dirty tree}"
|
||||
exit "$SUCCESS"
|
||||
fi
|
||||
|
||||
if ! check_uapi_files "$base_ref" "$past_ref" "$abi_error_log"; then
|
||||
exit "$FAIL_ABI"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
MAX_THREADS=$(nproc)
|
||||
VERBOSE="false"
|
||||
IGNORE_AMBIGUOUS_CHANGES="false"
|
||||
quiet="false"
|
||||
local base_ref=""
|
||||
while getopts "hb:p:j:l:iqv" opt; do
|
||||
case $opt in
|
||||
h)
|
||||
print_usage
|
||||
exit "$SUCCESS"
|
||||
;;
|
||||
b)
|
||||
base_ref="$OPTARG"
|
||||
;;
|
||||
p)
|
||||
past_ref="$OPTARG"
|
||||
;;
|
||||
j)
|
||||
MAX_THREADS="$OPTARG"
|
||||
;;
|
||||
l)
|
||||
abi_error_log="$OPTARG"
|
||||
;;
|
||||
i)
|
||||
IGNORE_AMBIGUOUS_CHANGES="true"
|
||||
;;
|
||||
q)
|
||||
quiet="true"
|
||||
VERBOSE="false"
|
||||
;;
|
||||
v)
|
||||
VERBOSE="true"
|
||||
quiet="false"
|
||||
;;
|
||||
*)
|
||||
exit "$FAIL_PREREQ"
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$quiet" = "true" ]; then
|
||||
exec > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
run "$base_ref" "$past_ref" "$abi_error_log" "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
@ -82,21 +82,12 @@ LxPs()
|
||||
|
||||
thread_info_type = utils.CachedType("struct thread_info")
|
||||
|
||||
ia64_task_size = None
|
||||
|
||||
|
||||
def get_thread_info(task):
|
||||
thread_info_ptr_type = thread_info_type.get_type().pointer()
|
||||
if utils.is_target_arch("ia64"):
|
||||
global ia64_task_size
|
||||
if ia64_task_size is None:
|
||||
ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)")
|
||||
thread_info_addr = task.address + ia64_task_size
|
||||
thread_info = thread_info_addr.cast(thread_info_ptr_type)
|
||||
else:
|
||||
if task.type.fields()[0].type == thread_info_type.get_type():
|
||||
return task['thread_info']
|
||||
thread_info = task['stack'].cast(thread_info_ptr_type)
|
||||
if task.type.fields()[0].type == thread_info_type.get_type():
|
||||
return task['thread_info']
|
||||
thread_info = task['stack'].cast(thread_info_ptr_type)
|
||||
return thread_info.dereference()
|
||||
|
||||
|
||||
|
@ -16,9 +16,7 @@
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <getopt.h>
|
||||
#endif /* __GNU_LIBRARY__ */
|
||||
|
||||
#include "genksyms.h"
|
||||
/*----------------------------------------------------------------------*/
|
||||
@ -718,8 +716,6 @@ void error_with_pos(const char *fmt, ...)
|
||||
static void genksyms_usage(void)
|
||||
{
|
||||
fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
|
||||
#ifdef __GNU_LIBRARY__
|
||||
" -s, --symbol-prefix Select symbol prefix\n"
|
||||
" -d, --debug Increment the debug level (repeatable)\n"
|
||||
" -D, --dump Dump expanded symbol defs (for debugging only)\n"
|
||||
" -r, --reference file Read reference symbols from a file\n"
|
||||
@ -729,18 +725,6 @@ static void genksyms_usage(void)
|
||||
" -q, --quiet Disable warnings (default)\n"
|
||||
" -h, --help Print this message\n"
|
||||
" -V, --version Print the release version\n"
|
||||
#else /* __GNU_LIBRARY__ */
|
||||
" -s Select symbol prefix\n"
|
||||
" -d Increment the debug level (repeatable)\n"
|
||||
" -D Dump expanded symbol defs (for debugging only)\n"
|
||||
" -r file Read reference symbols from a file\n"
|
||||
" -T file Dump expanded types into file\n"
|
||||
" -p Preserve reference modversions or fail\n"
|
||||
" -w Enable warnings\n"
|
||||
" -q Disable warnings (default)\n"
|
||||
" -h Print this message\n"
|
||||
" -V Print the release version\n"
|
||||
#endif /* __GNU_LIBRARY__ */
|
||||
, stderr);
|
||||
}
|
||||
|
||||
@ -749,7 +733,6 @@ int main(int argc, char **argv)
|
||||
FILE *dumpfile = NULL, *ref_file = NULL;
|
||||
int o;
|
||||
|
||||
#ifdef __GNU_LIBRARY__
|
||||
struct option long_opts[] = {
|
||||
{"debug", 0, 0, 'd'},
|
||||
{"warnings", 0, 0, 'w'},
|
||||
@ -763,11 +746,8 @@ int main(int argc, char **argv)
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
|
||||
while ((o = getopt_long(argc, argv, "dwqVDr:T:ph",
|
||||
&long_opts[0], NULL)) != EOF)
|
||||
#else /* __GNU_LIBRARY__ */
|
||||
while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
|
||||
#endif /* __GNU_LIBRARY__ */
|
||||
switch (o) {
|
||||
case 'd':
|
||||
flag_debug++;
|
||||
|
42
scripts/git.orderFile
Normal file
42
scripts/git.orderFile
Normal file
@ -0,0 +1,42 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# order file for git, to produce patches which are easier to review
|
||||
# by diffing the important stuff like header changes first.
|
||||
#
|
||||
# one-off usage:
|
||||
# git diff -O scripts/git.orderFile ...
|
||||
#
|
||||
# add to git config:
|
||||
# git config diff.orderFile scripts/git.orderFile
|
||||
#
|
||||
|
||||
MAINTAINERS
|
||||
|
||||
# Documentation
|
||||
Documentation/*
|
||||
*.rst
|
||||
|
||||
# git-specific
|
||||
.gitignore
|
||||
scripts/git.orderFile
|
||||
|
||||
# build system
|
||||
Kconfig*
|
||||
*/Kconfig*
|
||||
Kbuild*
|
||||
*/Kbuild*
|
||||
Makefile*
|
||||
*/Makefile*
|
||||
*.mak
|
||||
*.mk
|
||||
scripts/*
|
||||
|
||||
# semantic patches
|
||||
*.cocci
|
||||
|
||||
# headers
|
||||
*types.h
|
||||
*.h
|
||||
|
||||
# code
|
||||
*.c
|
@ -17,7 +17,6 @@ arch/arm/kernel/head-nommu.o
|
||||
arch/arm/kernel/head.o
|
||||
arch/csky/kernel/head.o
|
||||
arch/hexagon/kernel/head.o
|
||||
arch/ia64/kernel/head.o
|
||||
arch/loongarch/kernel/head.o
|
||||
arch/m68k/68000/head.o
|
||||
arch/m68k/coldfire/head.o
|
||||
|
@ -27,6 +27,14 @@ KCONFIG_DEFCONFIG_LIST += \
|
||||
endif
|
||||
KCONFIG_DEFCONFIG_LIST += arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)
|
||||
|
||||
ifneq ($(findstring c, $(KBUILD_EXTRA_WARN)),)
|
||||
export KCONFIG_WARN_UNKNOWN_SYMBOLS=1
|
||||
endif
|
||||
|
||||
ifneq ($(findstring e, $(KBUILD_EXTRA_WARN)),)
|
||||
export KCONFIG_WERROR=1
|
||||
endif
|
||||
|
||||
# We need this, in case the user has it in its environment
|
||||
unexport CONFIG_
|
||||
|
||||
@ -99,7 +107,7 @@ config-fragments = $(call configfiles,$@)
|
||||
|
||||
%.config: $(obj)/conf
|
||||
$(if $(config-fragments),, $(error $@ fragment does not exists on this architecture))
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(config-fragments)
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments)
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
|
||||
|
||||
PHONY += tinyconfig
|
||||
@ -166,7 +174,7 @@ conf-objs := conf.o $(common-objs)
|
||||
|
||||
# nconf: Used for the nconfig target based on ncurses
|
||||
hostprogs += nconf
|
||||
nconf-objs := nconf.o nconf.gui.o $(common-objs)
|
||||
nconf-objs := nconf.o nconf.gui.o mnconf-common.o $(common-objs)
|
||||
|
||||
HOSTLDLIBS_nconf = $(call read-file, $(obj)/nconf-libs)
|
||||
HOSTCFLAGS_nconf.o = $(call read-file, $(obj)/nconf-cflags)
|
||||
@ -179,7 +187,7 @@ $(obj)/nconf.o $(obj)/nconf.gui.o: | $(obj)/nconf-cflags
|
||||
hostprogs += mconf
|
||||
lxdialog := $(addprefix lxdialog/, \
|
||||
checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
|
||||
mconf-objs := mconf.o $(lxdialog) $(common-objs)
|
||||
mconf-objs := mconf.o $(lxdialog) mnconf-common.o $(common-objs)
|
||||
|
||||
HOSTLDLIBS_mconf = $(call read-file, $(obj)/mconf-libs)
|
||||
$(foreach f, mconf.o $(lxdialog), \
|
||||
|
@ -827,6 +827,9 @@ int main(int ac, char **av)
|
||||
break;
|
||||
}
|
||||
|
||||
if (conf_errors())
|
||||
exit(1);
|
||||
|
||||
if (sync_kconfig) {
|
||||
name = getenv("KCONFIG_NOSILENTUPDATE");
|
||||
if (name && *name) {
|
||||
@ -890,6 +893,9 @@ int main(int ac, char **av)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sym_dep_errors())
|
||||
exit(1);
|
||||
|
||||
if (input_mode == savedefconfig) {
|
||||
if (conf_write_defconfig(defconfig_file)) {
|
||||
fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
|
||||
|
@ -155,6 +155,13 @@ static void conf_message(const char *fmt, ...)
|
||||
static const char *conf_filename;
|
||||
static int conf_lineno, conf_warnings;
|
||||
|
||||
bool conf_errors(void)
|
||||
{
|
||||
if (conf_warnings)
|
||||
return getenv("KCONFIG_WERROR");
|
||||
return false;
|
||||
}
|
||||
|
||||
static void conf_warning(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@ -289,16 +296,12 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
||||
#define LINE_GROWTH 16
|
||||
static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
|
||||
{
|
||||
char *nline;
|
||||
size_t new_size = slen + 1;
|
||||
|
||||
if (new_size > *n) {
|
||||
new_size += LINE_GROWTH - 1;
|
||||
new_size *= 2;
|
||||
nline = xrealloc(*lineptr, new_size);
|
||||
if (!nline)
|
||||
return -1;
|
||||
|
||||
*lineptr = nline;
|
||||
*lineptr = xrealloc(*lineptr, new_size);
|
||||
*n = new_size;
|
||||
}
|
||||
|
||||
@ -341,19 +344,37 @@ static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* like getline(), but the newline character is stripped away */
|
||||
static ssize_t getline_stripped(char **lineptr, size_t *n, FILE *stream)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
len = compat_getline(lineptr, n, stream);
|
||||
|
||||
if (len > 0 && (*lineptr)[len - 1] == '\n') {
|
||||
len--;
|
||||
(*lineptr)[len] = '\0';
|
||||
|
||||
if (len > 0 && (*lineptr)[len - 1] == '\r') {
|
||||
len--;
|
||||
(*lineptr)[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int conf_read_simple(const char *name, int def)
|
||||
{
|
||||
FILE *in = NULL;
|
||||
char *line = NULL;
|
||||
size_t line_asize = 0;
|
||||
char *p, *p2;
|
||||
char *p, *val;
|
||||
struct symbol *sym;
|
||||
int i, def_flags;
|
||||
const char *warn_unknown;
|
||||
const char *werror;
|
||||
const char *warn_unknown, *sym_name;
|
||||
|
||||
warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS");
|
||||
werror = getenv("KCONFIG_WERROR");
|
||||
if (name) {
|
||||
in = zconf_fopen(name);
|
||||
} else {
|
||||
@ -417,8 +438,7 @@ int conf_read_simple(const char *name, int def)
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
case S_STRING:
|
||||
if (sym->def[def].val)
|
||||
free(sym->def[def].val);
|
||||
free(sym->def[def].val);
|
||||
/* fall through */
|
||||
default:
|
||||
sym->def[def].val = NULL;
|
||||
@ -426,90 +446,68 @@ int conf_read_simple(const char *name, int def)
|
||||
}
|
||||
}
|
||||
|
||||
while (compat_getline(&line, &line_asize, in) != -1) {
|
||||
while (getline_stripped(&line, &line_asize, in) != -1) {
|
||||
conf_lineno++;
|
||||
sym = NULL;
|
||||
|
||||
if (!line[0]) /* blank line */
|
||||
continue;
|
||||
|
||||
if (line[0] == '#') {
|
||||
if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
|
||||
if (line[1] != ' ')
|
||||
continue;
|
||||
p = strchr(line + 2 + strlen(CONFIG_), ' ');
|
||||
p = line + 2;
|
||||
if (memcmp(p, CONFIG_, strlen(CONFIG_)))
|
||||
continue;
|
||||
sym_name = p + strlen(CONFIG_);
|
||||
p = strchr(sym_name, ' ');
|
||||
if (!p)
|
||||
continue;
|
||||
*p++ = 0;
|
||||
if (strncmp(p, "is not set", 10))
|
||||
if (strcmp(p, "is not set"))
|
||||
continue;
|
||||
if (def == S_DEF_USER) {
|
||||
sym = sym_find(line + 2 + strlen(CONFIG_));
|
||||
if (!sym) {
|
||||
if (warn_unknown)
|
||||
conf_warning("unknown symbol: %s",
|
||||
line + 2 + strlen(CONFIG_));
|
||||
|
||||
conf_set_changed(true);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
|
||||
if (sym->type == S_UNKNOWN)
|
||||
sym->type = S_BOOLEAN;
|
||||
}
|
||||
if (sym->flags & def_flags) {
|
||||
conf_warning("override: reassigning to symbol %s", sym->name);
|
||||
}
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
sym->def[def].tri = no;
|
||||
sym->flags |= def_flags;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
|
||||
p = strchr(line + strlen(CONFIG_), '=');
|
||||
if (!p)
|
||||
continue;
|
||||
*p++ = 0;
|
||||
p2 = strchr(p, '\n');
|
||||
if (p2) {
|
||||
*p2-- = 0;
|
||||
if (*p2 == '\r')
|
||||
*p2 = 0;
|
||||
}
|
||||
|
||||
sym = sym_find(line + strlen(CONFIG_));
|
||||
if (!sym) {
|
||||
if (def == S_DEF_AUTO) {
|
||||
/*
|
||||
* Reading from include/config/auto.conf
|
||||
* If CONFIG_FOO previously existed in
|
||||
* auto.conf but it is missing now,
|
||||
* include/config/FOO must be touched.
|
||||
*/
|
||||
conf_touch_dep(line + strlen(CONFIG_));
|
||||
} else {
|
||||
if (warn_unknown)
|
||||
conf_warning("unknown symbol: %s",
|
||||
line + strlen(CONFIG_));
|
||||
|
||||
conf_set_changed(true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sym->flags & def_flags) {
|
||||
conf_warning("override: reassigning to symbol %s", sym->name);
|
||||
}
|
||||
if (conf_set_sym_val(sym, def, def_flags, p))
|
||||
continue;
|
||||
val = "n";
|
||||
} else {
|
||||
if (line[0] != '\r' && line[0] != '\n')
|
||||
conf_warning("unexpected data: %.*s",
|
||||
(int)strcspn(line, "\r\n"), line);
|
||||
if (memcmp(line, CONFIG_, strlen(CONFIG_))) {
|
||||
conf_warning("unexpected data: %s", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
sym_name = line + strlen(CONFIG_);
|
||||
p = strchr(sym_name, '=');
|
||||
if (!p) {
|
||||
conf_warning("unexpected data: %s", line);
|
||||
continue;
|
||||
}
|
||||
*p = 0;
|
||||
val = p + 1;
|
||||
}
|
||||
|
||||
sym = sym_find(sym_name);
|
||||
if (!sym) {
|
||||
if (def == S_DEF_AUTO) {
|
||||
/*
|
||||
* Reading from include/config/auto.conf.
|
||||
* If CONFIG_FOO previously existed in auto.conf
|
||||
* but it is missing now, include/config/FOO
|
||||
* must be touched.
|
||||
*/
|
||||
conf_touch_dep(sym_name);
|
||||
} else {
|
||||
if (warn_unknown)
|
||||
conf_warning("unknown symbol: %s", sym_name);
|
||||
|
||||
conf_set_changed(true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sym->flags & def_flags)
|
||||
conf_warning("override: reassigning to symbol %s", sym->name);
|
||||
|
||||
if (conf_set_sym_val(sym, def, def_flags, val))
|
||||
continue;
|
||||
|
||||
if (sym && sym_is_choice_value(sym)) {
|
||||
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||
switch (sym->def[def].tri) {
|
||||
@ -533,9 +531,6 @@ int conf_read_simple(const char *name, int def)
|
||||
free(line);
|
||||
fclose(in);
|
||||
|
||||
if (conf_warnings && werror)
|
||||
exit(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -594,7 +589,7 @@ int conf_read(const char *name)
|
||||
/* Reset a string value if it's out of range */
|
||||
if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
|
||||
break;
|
||||
sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
|
||||
sym->flags &= ~SYMBOL_VALID;
|
||||
conf_unsaved++;
|
||||
break;
|
||||
default:
|
||||
|
@ -1131,7 +1131,6 @@ static int expr_compare_type(enum expr_type t1, enum expr_type t2)
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
printf("[%dgt%d?]", t1, t2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -99,8 +99,6 @@ bool menu_is_visible(struct menu *menu);
|
||||
bool menu_has_prompt(struct menu *menu);
|
||||
const char *menu_get_prompt(struct menu *menu);
|
||||
struct menu *menu_get_parent_menu(struct menu *menu);
|
||||
bool menu_has_help(struct menu *menu);
|
||||
const char *menu_get_help(struct menu *menu);
|
||||
int get_jump_key_char(void);
|
||||
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
|
||||
void menu_get_ext_help(struct menu *menu, struct gstr *help);
|
||||
|
@ -1,4 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef LKC_PROTO_H
|
||||
#define LKC_PROTO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* confdata.c */
|
||||
@ -12,6 +15,7 @@ void conf_set_changed(bool val);
|
||||
bool conf_get_changed(void);
|
||||
void conf_set_changed_callback(void (*fn)(void));
|
||||
void conf_set_message_callback(void (*fn)(const char *s));
|
||||
bool conf_errors(void);
|
||||
|
||||
/* symbol.c */
|
||||
extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
|
||||
@ -22,6 +26,7 @@ void print_symbol_for_listconfig(struct symbol *sym);
|
||||
struct symbol ** sym_re_search(const char *pattern);
|
||||
const char * sym_type_name(enum symbol_type type);
|
||||
void sym_calc_value(struct symbol *sym);
|
||||
bool sym_dep_errors(void);
|
||||
enum symbol_type sym_get_type(struct symbol *sym);
|
||||
bool sym_tristate_within_range(struct symbol *sym,tristate tri);
|
||||
bool sym_set_tristate_value(struct symbol *sym,tristate tri);
|
||||
@ -50,3 +55,5 @@ char *expand_one_token(const char **str);
|
||||
|
||||
/* expr.c */
|
||||
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
|
||||
|
||||
#endif /* LKC_PROTO_H */
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "lkc.h"
|
||||
#include "lxdialog/dialog.h"
|
||||
#include "mnconf-common.h"
|
||||
|
||||
static const char mconf_readme[] =
|
||||
"Overview\n"
|
||||
@ -247,7 +248,7 @@ search_help[] =
|
||||
" -> PCI support (PCI [=y])\n"
|
||||
"(1) -> PCI access mode (<choice> [=y])\n"
|
||||
" Defined at drivers/pci/Kconfig:47\n"
|
||||
" Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
|
||||
" Depends on: X86_LOCAL_APIC && X86_IO_APIC\n"
|
||||
" Selects: LIBCRC32\n"
|
||||
" Selected by: BAR [=n]\n"
|
||||
"-----------------------------------------------------------------\n"
|
||||
@ -286,7 +287,6 @@ static int single_menu_mode;
|
||||
static int show_all_options;
|
||||
static int save_and_exit;
|
||||
static int silent;
|
||||
static int jump_key_char;
|
||||
|
||||
static void conf(struct menu *menu, struct menu *active_menu);
|
||||
|
||||
@ -378,58 +378,6 @@ static void show_help(struct menu *menu)
|
||||
str_free(&help);
|
||||
}
|
||||
|
||||
struct search_data {
|
||||
struct list_head *head;
|
||||
struct menu *target;
|
||||
};
|
||||
|
||||
static int next_jump_key(int key)
|
||||
{
|
||||
if (key < '1' || key > '9')
|
||||
return '1';
|
||||
|
||||
key++;
|
||||
|
||||
if (key > '9')
|
||||
key = '1';
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static int handle_search_keys(int key, size_t start, size_t end, void *_data)
|
||||
{
|
||||
struct search_data *data = _data;
|
||||
struct jump_key *pos;
|
||||
int index = 0;
|
||||
|
||||
if (key < '1' || key > '9')
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(pos, data->head, entries) {
|
||||
index = next_jump_key(index);
|
||||
|
||||
if (pos->offset < start)
|
||||
continue;
|
||||
|
||||
if (pos->offset >= end)
|
||||
break;
|
||||
|
||||
if (key == index) {
|
||||
data->target = pos->target;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_jump_key_char(void)
|
||||
{
|
||||
jump_key_char = next_jump_key(jump_key_char);
|
||||
|
||||
return jump_key_char;
|
||||
}
|
||||
|
||||
static void search_conf(void)
|
||||
{
|
||||
struct symbol **sym_arr;
|
||||
|
@ -673,19 +673,6 @@ struct menu *menu_get_parent_menu(struct menu *menu)
|
||||
return menu;
|
||||
}
|
||||
|
||||
bool menu_has_help(struct menu *menu)
|
||||
{
|
||||
return menu->help != NULL;
|
||||
}
|
||||
|
||||
const char *menu_get_help(struct menu *menu)
|
||||
{
|
||||
if (menu->help)
|
||||
return menu->help;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
static void get_def_str(struct gstr *r, struct menu *menu)
|
||||
{
|
||||
str_printf(r, "Defined at %s:%d\n",
|
||||
@ -856,10 +843,10 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
|
||||
struct symbol *sym = menu->sym;
|
||||
const char *help_text = nohelp_text;
|
||||
|
||||
if (menu_has_help(menu)) {
|
||||
if (menu->help) {
|
||||
if (sym->name)
|
||||
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
|
||||
help_text = menu_get_help(menu);
|
||||
help_text = menu->help;
|
||||
}
|
||||
str_printf(help, "%s\n", help_text);
|
||||
if (sym)
|
||||
|
53
scripts/kconfig/mnconf-common.c
Normal file
53
scripts/kconfig/mnconf-common.c
Normal file
@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include "expr.h"
|
||||
#include "list.h"
|
||||
#include "mnconf-common.h"
|
||||
|
||||
int jump_key_char;
|
||||
|
||||
int next_jump_key(int key)
|
||||
{
|
||||
if (key < '1' || key > '9')
|
||||
return '1';
|
||||
|
||||
key++;
|
||||
|
||||
if (key > '9')
|
||||
key = '1';
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
int handle_search_keys(int key, size_t start, size_t end, void *_data)
|
||||
{
|
||||
struct search_data *data = _data;
|
||||
struct jump_key *pos;
|
||||
int index = 0;
|
||||
|
||||
if (key < '1' || key > '9')
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(pos, data->head, entries) {
|
||||
index = next_jump_key(index);
|
||||
|
||||
if (pos->offset < start)
|
||||
continue;
|
||||
|
||||
if (pos->offset >= end)
|
||||
break;
|
||||
|
||||
if (key == index) {
|
||||
data->target = pos->target;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_jump_key_char(void)
|
||||
{
|
||||
jump_key_char = next_jump_key(jump_key_char);
|
||||
|
||||
return jump_key_char;
|
||||
}
|
18
scripts/kconfig/mnconf-common.h
Normal file
18
scripts/kconfig/mnconf-common.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef MNCONF_COMMON_H
|
||||
#define MNCONF_COMMON_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct search_data {
|
||||
struct list_head *head;
|
||||
struct menu *target;
|
||||
};
|
||||
|
||||
extern int jump_key_char;
|
||||
|
||||
int next_jump_key(int key);
|
||||
int handle_search_keys(int key, size_t start, size_t end, void *_data);
|
||||
int get_jump_key_char(void);
|
||||
|
||||
#endif /* MNCONF_COMMON_H */
|
@ -12,6 +12,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lkc.h"
|
||||
#include "mnconf-common.h"
|
||||
#include "nconf.h"
|
||||
#include <ctype.h>
|
||||
|
||||
@ -216,7 +217,7 @@ search_help[] =
|
||||
"Symbol: FOO [ = m]\n"
|
||||
"Prompt: Foo bus is used to drive the bar HW\n"
|
||||
"Defined at drivers/pci/Kconfig:47\n"
|
||||
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
|
||||
"Depends on: X86_LOCAL_APIC && X86_IO_APIC\n"
|
||||
"Location:\n"
|
||||
" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
|
||||
" -> PCI support (PCI [ = y])\n"
|
||||
@ -279,7 +280,6 @@ static const char *current_instructions = menu_instructions;
|
||||
|
||||
static char *dialog_input_result;
|
||||
static int dialog_input_result_len;
|
||||
static int jump_key_char;
|
||||
|
||||
static void selected_conf(struct menu *menu, struct menu *active_menu);
|
||||
static void conf(struct menu *menu);
|
||||
@ -691,57 +691,6 @@ static int do_exit(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct search_data {
|
||||
struct list_head *head;
|
||||
struct menu *target;
|
||||
};
|
||||
|
||||
static int next_jump_key(int key)
|
||||
{
|
||||
if (key < '1' || key > '9')
|
||||
return '1';
|
||||
|
||||
key++;
|
||||
|
||||
if (key > '9')
|
||||
key = '1';
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static int handle_search_keys(int key, size_t start, size_t end, void *_data)
|
||||
{
|
||||
struct search_data *data = _data;
|
||||
struct jump_key *pos;
|
||||
int index = 0;
|
||||
|
||||
if (key < '1' || key > '9')
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(pos, data->head, entries) {
|
||||
index = next_jump_key(index);
|
||||
|
||||
if (pos->offset < start)
|
||||
continue;
|
||||
|
||||
if (pos->offset >= end)
|
||||
break;
|
||||
|
||||
if (key == index) {
|
||||
data->target = pos->target;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_jump_key_char(void)
|
||||
{
|
||||
jump_key_char = next_jump_key(jump_key_char);
|
||||
|
||||
return jump_key_char;
|
||||
}
|
||||
|
||||
static void search_conf(void)
|
||||
{
|
||||
|
@ -29,14 +29,9 @@ struct symbol symbol_no = {
|
||||
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
||||
};
|
||||
|
||||
static struct symbol symbol_empty = {
|
||||
.name = "",
|
||||
.curr = { "", no },
|
||||
.flags = SYMBOL_VALID,
|
||||
};
|
||||
|
||||
struct symbol *modules_sym;
|
||||
static tristate modules_val;
|
||||
static int sym_warnings;
|
||||
|
||||
enum symbol_type sym_get_type(struct symbol *sym)
|
||||
{
|
||||
@ -317,6 +312,14 @@ static void sym_warn_unmet_dep(struct symbol *sym)
|
||||
" Selected by [m]:\n");
|
||||
|
||||
fputs(str_get(&gs), stderr);
|
||||
sym_warnings++;
|
||||
}
|
||||
|
||||
bool sym_dep_errors(void)
|
||||
{
|
||||
if (sym_warnings)
|
||||
return getenv("KCONFIG_WERROR");
|
||||
return false;
|
||||
}
|
||||
|
||||
void sym_calc_value(struct symbol *sym)
|
||||
@ -344,9 +347,13 @@ void sym_calc_value(struct symbol *sym)
|
||||
|
||||
switch (sym->type) {
|
||||
case S_INT:
|
||||
newval.val = "0";
|
||||
break;
|
||||
case S_HEX:
|
||||
newval.val = "0x0";
|
||||
break;
|
||||
case S_STRING:
|
||||
newval = symbol_empty.curr;
|
||||
newval.val = "";
|
||||
break;
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
@ -697,13 +704,12 @@ const char *sym_get_string_default(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
struct symbol *ds;
|
||||
const char *str;
|
||||
const char *str = "";
|
||||
tristate val;
|
||||
|
||||
sym_calc_visibility(sym);
|
||||
sym_calc_value(modules_sym);
|
||||
val = symbol_no.curr.tri;
|
||||
str = symbol_empty.curr.val;
|
||||
|
||||
/* If symbol has a default value look it up */
|
||||
prop = sym_get_default_prop(sym);
|
||||
@ -753,14 +759,17 @@ const char *sym_get_string_default(struct symbol *sym)
|
||||
case yes: return "y";
|
||||
}
|
||||
case S_INT:
|
||||
if (!str[0])
|
||||
str = "0";
|
||||
break;
|
||||
case S_HEX:
|
||||
return str;
|
||||
case S_STRING:
|
||||
return str;
|
||||
case S_UNKNOWN:
|
||||
if (!str[0])
|
||||
str = "0x0";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
return str;
|
||||
}
|
||||
|
||||
const char *sym_get_string_value(struct symbol *sym)
|
||||
|
@ -42,8 +42,7 @@ struct gstr str_new(void)
|
||||
/* Free storage for growable string */
|
||||
void str_free(struct gstr *gs)
|
||||
{
|
||||
if (gs->s)
|
||||
free(gs->s);
|
||||
free(gs->s);
|
||||
gs->s = NULL;
|
||||
gs->len = 0;
|
||||
}
|
||||
|
@ -60,8 +60,7 @@ static unsigned int nr_unresolved;
|
||||
|
||||
#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr))
|
||||
|
||||
void __attribute__((format(printf, 2, 3)))
|
||||
modpost_log(enum loglevel loglevel, const char *fmt, ...)
|
||||
void modpost_log(enum loglevel loglevel, const char *fmt, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
|
||||
@ -91,6 +90,9 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
|
||||
error_occurred = true;
|
||||
}
|
||||
|
||||
void __attribute__((alias("modpost_log")))
|
||||
modpost_log_noret(enum loglevel loglevel, const char *fmt, ...);
|
||||
|
||||
static inline bool strends(const char *str, const char *postfix)
|
||||
{
|
||||
if (strlen(str) < strlen(postfix))
|
||||
@ -474,11 +476,9 @@ static int parse_elf(struct elf_info *info, const char *filename)
|
||||
fatal("%s: not relocatable object.", filename);
|
||||
|
||||
/* Check if file offset is correct */
|
||||
if (hdr->e_shoff > info->size) {
|
||||
if (hdr->e_shoff > info->size)
|
||||
fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n",
|
||||
(unsigned long)hdr->e_shoff, filename, info->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hdr->e_shnum == SHN_UNDEF) {
|
||||
/*
|
||||
@ -516,12 +516,11 @@ static int parse_elf(struct elf_info *info, const char *filename)
|
||||
const char *secname;
|
||||
int nobits = sechdrs[i].sh_type == SHT_NOBITS;
|
||||
|
||||
if (!nobits && sechdrs[i].sh_offset > info->size) {
|
||||
if (!nobits && sechdrs[i].sh_offset > info->size)
|
||||
fatal("%s is truncated. sechdrs[i].sh_offset=%lu > sizeof(*hrd)=%zu\n",
|
||||
filename, (unsigned long)sechdrs[i].sh_offset,
|
||||
sizeof(*hdr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
secname = secstrings + sechdrs[i].sh_name;
|
||||
if (strcmp(secname, ".modinfo") == 0) {
|
||||
if (nobits)
|
||||
@ -1419,7 +1418,7 @@ static void section_rel(struct module *mod, struct elf_info *elf,
|
||||
|
||||
for (rel = start; rel < stop; rel++) {
|
||||
Elf_Sym *tsym;
|
||||
Elf_Addr taddr = 0, r_offset;
|
||||
Elf_Addr taddr, r_offset;
|
||||
unsigned int r_type, r_sym;
|
||||
void *loc;
|
||||
|
||||
|
@ -197,7 +197,11 @@ enum loglevel {
|
||||
LOG_FATAL
|
||||
};
|
||||
|
||||
void modpost_log(enum loglevel loglevel, const char *fmt, ...);
|
||||
void __attribute__((format(printf, 2, 3)))
|
||||
modpost_log(enum loglevel loglevel, const char *fmt, ...);
|
||||
|
||||
void __attribute__((format(printf, 2, 3), noreturn))
|
||||
modpost_log_noret(enum loglevel loglevel, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* warn - show the given message, then let modpost continue running, still
|
||||
@ -214,4 +218,4 @@ void modpost_log(enum loglevel loglevel, const char *fmt, ...);
|
||||
*/
|
||||
#define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args)
|
||||
#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args)
|
||||
#define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args)
|
||||
#define fatal(fmt, args...) modpost_log_noret(LOG_FATAL, fmt, ##args)
|
||||
|
@ -25,35 +25,20 @@ if_enabled_echo() {
|
||||
}
|
||||
|
||||
create_package() {
|
||||
local pname="$1" pdir="$2"
|
||||
local dpkg_deb_opts
|
||||
export DH_OPTIONS="-p${1}"
|
||||
|
||||
mkdir -m 755 -p "$pdir/DEBIAN"
|
||||
mkdir -p "$pdir/usr/share/doc/$pname"
|
||||
cp debian/copyright "$pdir/usr/share/doc/$pname/"
|
||||
cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian"
|
||||
gzip -n -9 "$pdir/usr/share/doc/$pname/changelog.Debian"
|
||||
sh -c "cd '$pdir'; find . -type f ! -path './DEBIAN/*' -printf '%P\0' \
|
||||
| xargs -r0 md5sum > DEBIAN/md5sums"
|
||||
|
||||
# Fix ownership and permissions
|
||||
if [ "$DEB_RULES_REQUIRES_ROOT" = "no" ]; then
|
||||
dpkg_deb_opts="--root-owner-group"
|
||||
else
|
||||
chown -R root:root "$pdir"
|
||||
fi
|
||||
# a+rX in case we are in a restrictive umask environment like 0077
|
||||
# ug-s in case we build in a setuid/setgid directory
|
||||
chmod -R go-w,a+rX,ug-s "$pdir"
|
||||
|
||||
# Create the package
|
||||
dpkg-gencontrol -p$pname -P"$pdir"
|
||||
dpkg-deb $dpkg_deb_opts ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS} --build "$pdir" ..
|
||||
dh_installdocs
|
||||
dh_installchangelogs
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb -- ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS}
|
||||
}
|
||||
|
||||
install_linux_image () {
|
||||
pdir=$1
|
||||
pname=$2
|
||||
pname=$1
|
||||
pdir=debian/$1
|
||||
|
||||
rm -rf ${pdir}
|
||||
|
||||
@ -62,7 +47,7 @@ install_linux_image () {
|
||||
${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install
|
||||
fi
|
||||
|
||||
${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install
|
||||
${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" INSTALL_MOD_STRIP=1 modules_install
|
||||
rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build"
|
||||
|
||||
# Install the kernel
|
||||
@ -122,26 +107,22 @@ install_linux_image () {
|
||||
}
|
||||
|
||||
install_linux_image_dbg () {
|
||||
pdir=$1
|
||||
image_pdir=$2
|
||||
pdir=debian/$1
|
||||
|
||||
rm -rf ${pdir}
|
||||
|
||||
for module in $(find ${image_pdir}/lib/modules/ -name *.ko -printf '%P\n'); do
|
||||
module=lib/modules/${module}
|
||||
mkdir -p $(dirname ${pdir}/usr/lib/debug/${module})
|
||||
# only keep debug symbols in the debug file
|
||||
${OBJCOPY} --only-keep-debug ${image_pdir}/${module} ${pdir}/usr/lib/debug/${module}
|
||||
# strip original module from debug symbols
|
||||
${OBJCOPY} --strip-debug ${image_pdir}/${module}
|
||||
# then add a link to those
|
||||
${OBJCOPY} --add-gnu-debuglink=${pdir}/usr/lib/debug/${module} ${image_pdir}/${module}
|
||||
done
|
||||
# Parse modules.order directly because 'make modules_install' may sign,
|
||||
# compress modules, and then run unneeded depmod.
|
||||
while read -r mod; do
|
||||
mod="${mod%.o}.ko"
|
||||
dbg="${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/kernel/${mod}"
|
||||
buildid=$("${READELF}" -n "${mod}" | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p')
|
||||
link="${pdir}/usr/lib/debug/.build-id/${buildid}.debug"
|
||||
|
||||
# re-sign stripped modules
|
||||
if is_enabled CONFIG_MODULE_SIG_ALL; then
|
||||
${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${image_pdir}" modules_sign
|
||||
fi
|
||||
mkdir -p "${dbg%/*}" "${link%/*}"
|
||||
"${OBJCOPY}" --only-keep-debug "${mod}" "${dbg}"
|
||||
ln -sf --relative "${dbg}" "${link}"
|
||||
done < modules.order
|
||||
|
||||
# Build debug package
|
||||
# Different tools want the image in different locations
|
||||
@ -156,8 +137,8 @@ install_linux_image_dbg () {
|
||||
}
|
||||
|
||||
install_kernel_headers () {
|
||||
pdir=$1
|
||||
version=$2
|
||||
pdir=debian/$1
|
||||
version=${1#linux-headers-}
|
||||
|
||||
rm -rf $pdir
|
||||
|
||||
@ -168,18 +149,16 @@ install_kernel_headers () {
|
||||
}
|
||||
|
||||
install_libc_headers () {
|
||||
pdir=$1
|
||||
pdir=debian/$1
|
||||
|
||||
rm -rf $pdir
|
||||
|
||||
$MAKE -f $srctree/Makefile headers
|
||||
$MAKE -f $srctree/Makefile headers_install INSTALL_HDR_PATH=$pdir/usr
|
||||
|
||||
# move asm headers to /usr/include/<libc-machine>/asm to match the structure
|
||||
# used by Debian-based distros (to support multi-arch)
|
||||
host_arch=$(dpkg-architecture -a$DEB_HOST_ARCH -qDEB_HOST_MULTIARCH)
|
||||
mkdir $pdir/usr/include/$host_arch
|
||||
mv $pdir/usr/include/asm $pdir/usr/include/$host_arch/
|
||||
mkdir "$pdir/usr/include/${DEB_HOST_MULTIARCH}"
|
||||
mv "$pdir/usr/include/asm" "$pdir/usr/include/${DEB_HOST_MULTIARCH}"
|
||||
}
|
||||
|
||||
rm -f debian/files
|
||||
@ -190,30 +169,13 @@ for package in ${packages_enabled}
|
||||
do
|
||||
case ${package} in
|
||||
*-dbg)
|
||||
# This must be done after linux-image, that is, we expect the
|
||||
# debug package appears after linux-image in debian/control.
|
||||
install_linux_image_dbg debian/linux-image-dbg debian/linux-image;;
|
||||
install_linux_image_dbg "${package}";;
|
||||
linux-image-*|user-mode-linux-*)
|
||||
install_linux_image debian/linux-image ${package};;
|
||||
install_linux_image "${package}";;
|
||||
linux-libc-dev)
|
||||
install_libc_headers debian/linux-libc-dev;;
|
||||
install_libc_headers "${package}";;
|
||||
linux-headers-*)
|
||||
install_kernel_headers debian/linux-headers ${package#linux-headers-};;
|
||||
install_kernel_headers "${package}";;
|
||||
esac
|
||||
create_package "${package}"
|
||||
done
|
||||
|
||||
for package in ${packages_enabled}
|
||||
do
|
||||
case ${package} in
|
||||
*-dbg)
|
||||
create_package ${package} debian/linux-image-dbg;;
|
||||
linux-image-*|user-mode-linux-*)
|
||||
create_package ${package} debian/linux-image;;
|
||||
linux-libc-dev)
|
||||
create_package ${package} debian/linux-libc-dev;;
|
||||
linux-headers-*)
|
||||
create_package ${package} debian/linux-headers;;
|
||||
esac
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
@ -23,7 +23,6 @@ tmpdir=$1
|
||||
#
|
||||
rm -rf -- "${tmpdir}"
|
||||
mkdir -p -- "${tmpdir}/boot"
|
||||
dirs=boot
|
||||
|
||||
|
||||
#
|
||||
@ -38,12 +37,9 @@ fi
|
||||
|
||||
|
||||
#
|
||||
# Try to install modules
|
||||
# Install modules
|
||||
#
|
||||
if grep -q '^CONFIG_MODULES=y' include/config/auto.conf; then
|
||||
make ARCH="${ARCH}" -f ${srctree}/Makefile INSTALL_MOD_PATH="${tmpdir}" modules_install
|
||||
dirs="$dirs lib"
|
||||
fi
|
||||
make ARCH="${ARCH}" -f ${srctree}/Makefile INSTALL_MOD_PATH="${tmpdir}" modules_install
|
||||
|
||||
|
||||
#
|
||||
|
@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# Set up CROSS_COMPILE if not defined yet
|
||||
if [ "${CROSS_COMPILE+set}" != "set" -a "${DEB_HOST_ARCH}" != "${DEB_BUILD_ARCH}" ]; then
|
||||
echo CROSS_COMPILE=${DEB_HOST_GNU_TYPE}-
|
||||
fi
|
||||
|
||||
version=$(dpkg-parsechangelog -S Version)
|
||||
debian_revision="${version##*-}"
|
||||
|
||||
if [ "${version}" != "${debian_revision}" ]; then
|
||||
echo KBUILD_BUILD_VERSION=${debian_revision}
|
||||
fi
|
16
scripts/package/debian/copyright
Normal file
16
scripts/package/debian/copyright
Normal file
@ -0,0 +1,16 @@
|
||||
This is a packaged upstream version of the Linux kernel.
|
||||
|
||||
The sources may be found at most Linux archive sites, including:
|
||||
https://www.kernel.org/pub/linux/kernel
|
||||
|
||||
Copyright: 1991 - 2023 Linus Torvalds and others.
|
||||
|
||||
The git repository for mainline kernel development is at:
|
||||
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991.
|
||||
|
||||
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||
License version 2 can be found in `/usr/share/common-licenses/GPL-2'.
|
@ -1,33 +1,46 @@
|
||||
#!/usr/bin/make -f
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
include debian/rules.vars
|
||||
# in case debian/rules is executed directly
|
||||
export DEB_RULES_REQUIRES_ROOT := no
|
||||
|
||||
srctree ?= .
|
||||
include debian/rules.vars
|
||||
|
||||
ifneq (,$(filter-out parallel=1,$(filter parallel=%,$(DEB_BUILD_OPTIONS))))
|
||||
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
|
||||
MAKEFLAGS += -j$(NUMJOBS)
|
||||
endif
|
||||
|
||||
revision = $(lastword $(subst -, ,$(shell dpkg-parsechangelog -S Version)))
|
||||
CROSS_COMPILE ?= $(filter-out $(DEB_BUILD_GNU_TYPE)-, $(DEB_HOST_GNU_TYPE)-)
|
||||
make-opts = ARCH=$(ARCH) KERNELRELEASE=$(KERNELRELEASE) KBUILD_BUILD_VERSION=$(revision) $(addprefix CROSS_COMPILE=,$(CROSS_COMPILE))
|
||||
|
||||
.PHONY: binary binary-indep binary-arch
|
||||
binary: binary-arch binary-indep
|
||||
binary-indep: build-indep
|
||||
binary-arch: build-arch
|
||||
$(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) \
|
||||
KERNELRELEASE=$(KERNELRELEASE) \
|
||||
run-command KBUILD_RUN_COMMAND=+$(srctree)/scripts/package/builddeb
|
||||
$(MAKE) $(make-opts) \
|
||||
run-command KBUILD_RUN_COMMAND='+$$(srctree)/scripts/package/builddeb'
|
||||
|
||||
.PHONY: build build-indep build-arch
|
||||
build: build-arch build-indep
|
||||
build-indep:
|
||||
build-arch:
|
||||
$(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) \
|
||||
KERNELRELEASE=$(KERNELRELEASE) \
|
||||
$(shell $(srctree)/scripts/package/deb-build-option) \
|
||||
olddefconfig all
|
||||
$(MAKE) $(make-opts) olddefconfig
|
||||
$(MAKE) $(make-opts) $(if $(filter um,$(ARCH)),,headers) all
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf debian/files debian/linux-*
|
||||
$(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) clean
|
||||
rm -rf debian/files debian/linux-* debian/deb-env.vars*
|
||||
$(MAKE) ARCH=$(ARCH) clean
|
||||
|
||||
# If DEB_HOST_ARCH is empty, it is likely that debian/rules was executed
|
||||
# directly. Run 'dpkg-architecture --print-set --print-format=make' to
|
||||
# generate a makefile construct that exports all DEB_* variables.
|
||||
ifndef DEB_HOST_ARCH
|
||||
include debian/deb-env.vars
|
||||
|
||||
debian/deb-env.vars:
|
||||
dpkg-architecture -a$$(cat debian/arch) --print-set --print-format=make > $@.tmp
|
||||
mv $@.tmp $@
|
||||
endif
|
||||
|
@ -20,7 +20,7 @@ mkdir -p "${destdir}"
|
||||
find "arch/${SRCARCH}" -maxdepth 1 -name 'Makefile*'
|
||||
find include scripts -type f -o -type l
|
||||
find "arch/${SRCARCH}" -name Kbuild.platforms -o -name Platform
|
||||
find "arch/${SRCARCH}" -name include -o -name scripts -type d
|
||||
find "arch/${SRCARCH}" -name include -type d
|
||||
) | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${destdir}"
|
||||
|
||||
{
|
||||
|
@ -56,13 +56,7 @@ patch -p1 < %{SOURCE2}
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/boot
|
||||
%ifarch ia64
|
||||
mkdir -p %{buildroot}/boot/efi
|
||||
cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/efi/vmlinuz-%{KERNELRELEASE}
|
||||
ln -s efi/vmlinuz-%{KERNELRELEASE} %{buildroot}/boot/
|
||||
%else
|
||||
cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/vmlinuz-%{KERNELRELEASE}
|
||||
%endif
|
||||
%{make} %{makeflags} INSTALL_MOD_PATH=%{buildroot} modules_install
|
||||
%{make} %{makeflags} INSTALL_HDR_PATH=%{buildroot}/usr headers_install
|
||||
cp System.map %{buildroot}/boot/System.map-%{KERNELRELEASE}
|
||||
|
@ -26,7 +26,7 @@ set_debarch() {
|
||||
|
||||
# Attempt to find the correct Debian architecture
|
||||
case "$UTS_MACHINE" in
|
||||
i386|ia64|alpha|m68k|riscv*)
|
||||
i386|alpha|m68k|riscv*)
|
||||
debarch="$UTS_MACHINE" ;;
|
||||
x86_64)
|
||||
debarch=amd64 ;;
|
||||
@ -176,8 +176,6 @@ else
|
||||
fi
|
||||
|
||||
echo $debarch > debian/arch
|
||||
extra_build_depends=", $(if_enabled_echo CONFIG_UNWINDER_ORC libelf-dev:native)"
|
||||
extra_build_depends="$extra_build_depends, $(if_enabled_echo CONFIG_SYSTEM_TRUSTED_KEYRING libssl-dev:native)"
|
||||
|
||||
# Generate a simple changelog template
|
||||
cat <<EOF > debian/changelog
|
||||
@ -188,26 +186,6 @@ $sourcename ($packageversion) $distribution; urgency=low
|
||||
-- $maintainer $(date -R)
|
||||
EOF
|
||||
|
||||
# Generate copyright file
|
||||
cat <<EOF > debian/copyright
|
||||
This is a packaged upstream version of the Linux kernel.
|
||||
|
||||
The sources may be found at most Linux archive sites, including:
|
||||
https://www.kernel.org/pub/linux/kernel
|
||||
|
||||
Copyright: 1991 - 2018 Linus Torvalds and others.
|
||||
|
||||
The git repository for mainline kernel development is at:
|
||||
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991.
|
||||
|
||||
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||
License version 2 can be found in \`/usr/share/common-licenses/GPL-2'.
|
||||
EOF
|
||||
|
||||
# Generate a control file
|
||||
cat <<EOF > debian/control
|
||||
Source: $sourcename
|
||||
@ -215,7 +193,8 @@ Section: kernel
|
||||
Priority: optional
|
||||
Maintainer: $maintainer
|
||||
Rules-Requires-Root: no
|
||||
Build-Depends: bc, debhelper, rsync, kmod, cpio, bison, flex $extra_build_depends
|
||||
Build-Depends: debhelper-compat (= 12)
|
||||
Build-Depends-Arch: bc, bison, cpio, flex, kmod, libelf-dev:native, libssl-dev:native, rsync
|
||||
Homepage: https://www.kernel.org/
|
||||
|
||||
Package: $packagename-$version
|
||||
@ -268,6 +247,7 @@ ARCH := ${ARCH}
|
||||
KERNELRELEASE := ${KERNELRELEASE}
|
||||
EOF
|
||||
|
||||
cp "${srctree}/scripts/package/debian/copyright" debian/
|
||||
cp "${srctree}/scripts/package/debian/rules" debian/
|
||||
|
||||
exit 0
|
||||
|
@ -10,5 +10,5 @@ parts:
|
||||
kernel:
|
||||
plugin: kernel
|
||||
source: SRCTREE
|
||||
source-type: tar
|
||||
source-type: local
|
||||
kernel-with-firmware: false
|
||||
|
@ -590,7 +590,6 @@ static int do_file(char const *const fname)
|
||||
ideal_nop = ideal_nop4_arm64;
|
||||
is_fake_mcount64 = arm64_is_fake_mcount;
|
||||
break;
|
||||
case EM_IA_64: reltype = R_IA64_IMM64; break;
|
||||
case EM_MIPS: /* reltype: e_class */ break;
|
||||
case EM_LOONGARCH: /* reltype: e_class */ break;
|
||||
case EM_PPC: reltype = R_PPC_ADDR32; break;
|
||||
|
@ -275,13 +275,6 @@ if ($arch eq "x86_64") {
|
||||
$section_type = '%progbits';
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
|
||||
$type = ".quad";
|
||||
} elsif ($arch eq "ia64") {
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
|
||||
$type = "data8";
|
||||
|
||||
if ($is_module eq "0") {
|
||||
$cc .= " -mconstant-gp";
|
||||
}
|
||||
} elsif ($arch eq "sparc64") {
|
||||
# In the objdump output there are giblets like:
|
||||
# 0000000000000000 <igmp_net_exit-0x18>:
|
||||
|
@ -15,7 +15,6 @@ LZMA2OPTS=
|
||||
case $SRCARCH in
|
||||
x86) BCJ=--x86 ;;
|
||||
powerpc) BCJ=--powerpc ;;
|
||||
ia64) BCJ=--ia64; LZMA2OPTS=pb=4 ;;
|
||||
arm) BCJ=--arm ;;
|
||||
sparc) BCJ=--sparc ;;
|
||||
esac
|
||||
|
@ -27,6 +27,7 @@
|
||||
static unsigned int offset;
|
||||
static unsigned int ino = 721;
|
||||
static time_t default_mtime;
|
||||
static bool do_file_mtime;
|
||||
static bool do_csum = false;
|
||||
|
||||
struct file_handler {
|
||||
@ -329,6 +330,7 @@ static int cpio_mkfile(const char *name, const char *location,
|
||||
int file;
|
||||
int retval;
|
||||
int rc = -1;
|
||||
time_t mtime;
|
||||
int namesize;
|
||||
unsigned int i;
|
||||
uint32_t csum = 0;
|
||||
@ -347,16 +349,21 @@ static int cpio_mkfile(const char *name, const char *location,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buf.st_mtime > 0xffffffff) {
|
||||
fprintf(stderr, "%s: Timestamp exceeds maximum cpio timestamp, clipping.\n",
|
||||
location);
|
||||
buf.st_mtime = 0xffffffff;
|
||||
}
|
||||
if (do_file_mtime) {
|
||||
mtime = default_mtime;
|
||||
} else {
|
||||
mtime = buf.st_mtime;
|
||||
if (mtime > 0xffffffff) {
|
||||
fprintf(stderr, "%s: Timestamp exceeds maximum cpio timestamp, clipping.\n",
|
||||
location);
|
||||
mtime = 0xffffffff;
|
||||
}
|
||||
|
||||
if (buf.st_mtime < 0) {
|
||||
fprintf(stderr, "%s: Timestamp negative, clipping.\n",
|
||||
location);
|
||||
buf.st_mtime = 0;
|
||||
if (mtime < 0) {
|
||||
fprintf(stderr, "%s: Timestamp negative, clipping.\n",
|
||||
location);
|
||||
mtime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf.st_size > 0xffffffff) {
|
||||
@ -387,7 +394,7 @@ static int cpio_mkfile(const char *name, const char *location,
|
||||
(long) uid, /* uid */
|
||||
(long) gid, /* gid */
|
||||
nlinks, /* nlink */
|
||||
(long) buf.st_mtime, /* mtime */
|
||||
(long) mtime, /* mtime */
|
||||
size, /* filesize */
|
||||
3, /* major */
|
||||
1, /* minor */
|
||||
@ -536,8 +543,9 @@ static void usage(const char *prog)
|
||||
"file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n"
|
||||
"\n"
|
||||
"<timestamp> is time in seconds since Epoch that will be used\n"
|
||||
"as mtime for symlinks, special files and directories. The default\n"
|
||||
"is to use the current time for these entries.\n"
|
||||
"as mtime for symlinks, directories, regular and special files.\n"
|
||||
"The default is to use the current time for all files, but\n"
|
||||
"preserve modification time for regular files.\n"
|
||||
"-c: calculate and store 32-bit checksums for file data.\n",
|
||||
prog);
|
||||
}
|
||||
@ -594,6 +602,7 @@ int main (int argc, char *argv[])
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
do_file_mtime = true;
|
||||
break;
|
||||
case 'c':
|
||||
do_csum = true;
|
||||
|
Loading…
Reference in New Issue
Block a user