From 0f684317a7e0e7b6075ebfa5311b0c106eb1b802 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 3 Nov 2015 21:39:52 +1100 Subject: scripts/tags.sh: Teach tags about more powerpc macros Teach tags.sh about the powerpc PCI macros, eg. readl/writel etc. Signed-off-by: Michael Ellerman Signed-off-by: Michal Marek --- scripts/tags.sh | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index 262889046703..f69fa0c87312 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -200,6 +200,7 @@ exuberant() --regex-c++='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/'\ --regex-c++='/DEF_MMIO_(IN|OUT)_(X|D)\(([^,]*),\s*[^)]*\)/\3/' \ --regex-c++='/DEBUGGER_BOILERPLATE\(([^,]*)\)/\1/' \ + --regex-c++='/DEF_PCI_AC_(NO)?RET\(([^,]*),.*/\2/' \ --regex-c='/PCI_OP_READ\((\w*).*[1-4]\)/pci_bus_read_config_\1/' \ --regex-c='/PCI_OP_WRITE\((\w*).*[1-4]\)/pci_bus_write_config_\1/' \ --regex-c='/DEFINE_(MUTEX|SEMAPHORE|SPINLOCK)\((\w*)/\2/v/' \ -- cgit v1.2.3 From 8a9260aa96b5112856a8bfdbf80984bfbcb4003f Mon Sep 17 00:00:00 2001 From: Conchúr Navid Date: Sun, 8 Nov 2015 10:45:23 +0100 Subject: kernel-doc: Fix stripping of #define in enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The regex to strip single line #define's in enumerations depends on the fact that the defines are still stored on separate lines. But the surrounding code already removed newlines and replaced them with semicolons. For example a simple input like /** * enum flags - test flags * @flag1: first flag * @flag2: second flag * @flag3: third flag * @flag4: fourth flag */ enum flags { flag1 = BIT(0), flag2 = BIT(1), #define flags_small (flag1 | flag2) flag3 = BIT(2), flag4 = BIT(3), #define flags_big (flag2 | flag3) }; resulted in parsing warnings like warning: Enum value '#define flags_small (flag1 | flag2);flag3 = BIT(2)' not described in enum 'flags' warning: Enum value '#define flags_big (flag2 | flag3);' not described in enum 'flags' Signed-off-by: Conchúr Navid Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 125b906cd1d4..8313b49b6cd0 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1844,7 +1844,7 @@ sub dump_enum($$) { my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. - $x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums + $x =~ s@#\s*define\s+[^;]*;@@gos; # strip #define macros inside enums if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { $declaration_name = $1; -- cgit v1.2.3 From 4468e21eed2dd7ee8dc91d94dbd2ccb0d291fb07 Mon Sep 17 00:00:00 2001 From: Conchúr Navid Date: Sun, 8 Nov 2015 10:48:05 +0100 Subject: kernel-doc: Strip #ifdef/#endif in enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some enumerations in the kernel headers use #ifdef to reduce their size based on the the configuration. These lines have to be stripped to avoid parsing problems. For example a simple input like /** * enum flags - test flags * @flag1: first flag * @flag2: second flag */ enum flags { flag1 = BIT(0), #ifdef SECOND_FLAG flag2 = BIT(1), #endif }; resulted in parsing warnings like warning: Enum value '#ifdef SECOND_FLAG;flag2 = BIT(1)' not described in enum 'flags' warning: Enum value '#endif;' not described in enum 'flags' Signed-off-by: Conchúr Navid Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 8313b49b6cd0..f5c2971244a3 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1844,7 +1844,8 @@ sub dump_enum($$) { my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. - $x =~ s@#\s*define\s+[^;]*;@@gos; # strip #define macros inside enums + # strip #define macros inside enums + $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { $declaration_name = $1; -- cgit v1.2.3 From b22b5a9ef5309287b86bac9eb47f17a12671b770 Mon Sep 17 00:00:00 2001 From: Conchúr Navid Date: Sun, 8 Nov 2015 10:52:00 +0100 Subject: kernel-doc: Fix parsing of DECLARE_BITMAP in struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some documented structures in the kernel use DECLARE_BITMAP to create arrays of unsigned longs to store information using the bitmap functions. These have to be replaced with a parsable version for kernel-doc. For example a simple input like /** * struct something - some test * @members: active members */ struct something { DECLARE_BITMAP(members, MAX_MEMBERS); }; resulted in parsing warnings like warning: No description found for parameter 'MAX_MEMBERS)' warning: Excess struct/union/enum/typedef member 'members' description in 'something' Signed-off-by: Conchúr Navid Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index f5c2971244a3..9015b18d9f24 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1816,6 +1816,8 @@ sub dump_struct($$) { $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; $members =~ s/__aligned\s*\([^;]*\)//gos; $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos; + # replace DECLARE_BITMAP + $members =~ s/DECLARE_BITMAP\s*\(([^,)]+), ([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; create_parameterlist($members, ';', $file); check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested); -- cgit v1.2.3 From 4b63f603135022ca048524cd16f1c6a76a3f169d Mon Sep 17 00:00:00 2001 From: Riku Voipio Date: Tue, 1 Sep 2015 17:14:21 +0300 Subject: package Makefile: fix perf-tar targets when outdir is set building with $srctree != $objtree, perf-tar-* targets fail to read the MANIFEST file and add the PERF-VERSION-FILE needed by out-of-tree builds. The build errors and an incorrect tar is created: $ make O=build-x86 perf-targz-src-pkg TAR cat: ../tools/perf/MANIFEST: No such file or directory tar: perf-4.1.0-rc8/PERF-VERSION-FILE: Cannot stat: No such file or dir.. tar: Exiting with failure status due to previous errors Kbuild sets objtree to "." and srctree to ".." The command to output MANIFEST becomes: $(cd ..; echo $(cat ../tools/perf/MANIFEST)) Without MANIFEST, the entire kernel source tree is added to the perf source tarball. The *correct* fix is to keep the cd and remove srctree from cat command line since MANIFEST has wildcards that fail to expand working directory isn't srctree. Second, PERF-VERSION-FILE gets not added, because in-tree build path is hardcoded to Makefile: util/PERF-VERSION-GEN ../../$(perf-tar)/ 2>/dev/null) The PERF-VERSION-GEN needs to be run from tools/perf directory, and the output directory needs to be changed from relative to to absolute. This can be achieved using the $(CURDIR) variable. Also remove the error redirect to /dev/null which hid the error. Signed-off-by: Riku Voipio Signed-off-by: Michal Marek --- scripts/package/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/package/Makefile b/scripts/package/Makefile index 1aca224e8597..c2c7389bfbab 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile @@ -118,12 +118,12 @@ quiet_cmd_perf_tar = TAR cmd_perf_tar = \ git --git-dir=$(srctree)/.git archive --prefix=$(perf-tar)/ \ HEAD^{tree} $$(cd $(srctree); \ - echo $$(cat $(srctree)/tools/perf/MANIFEST)) \ + echo $$(cat tools/perf/MANIFEST)) \ -o $(perf-tar).tar; \ mkdir -p $(perf-tar); \ git --git-dir=$(srctree)/.git rev-parse HEAD > $(perf-tar)/HEAD; \ (cd $(srctree)/tools/perf; \ -util/PERF-VERSION-GEN ../../$(perf-tar)/ 2>/dev/null); \ +util/PERF-VERSION-GEN $(CURDIR)/$(perf-tar)/); \ tar rf $(perf-tar).tar $(perf-tar)/HEAD $(perf-tar)/PERF-VERSION-FILE; \ rm -r $(perf-tar); \ $(if $(findstring tar-src,$@),, \ -- cgit v1.2.3 From cf4f21938e13ea1533ebdcb21c46f1d998a44ee8 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 27 Oct 2015 14:02:24 +0100 Subject: kbuild: Allow to specify composite modules with modname-m This allows to write drm-$(CONFIG_AGP) += drm_agpsupport.o without having to handle CONFIG_AGP=y vs. CONFIG_AGP=m. Only support this syntax for modules, since built-in code depending on something modular cannot work and init/Makefile actually relies on the current semantics. There are a few drivers which adapted to the current semantics out of necessity; these are fixed to also work when the respective subsystem is modular. Acked-by: Peter Chen [chipidea] Signed-off-by: Michal Marek --- drivers/misc/ibmasm/ibmasm.h | 2 +- drivers/usb/chipidea/otg_fsm.h | 2 +- fs/logfs/logfs.h | 2 +- scripts/Makefile.build | 8 ++++++-- scripts/Makefile.lib | 4 ++-- 5 files changed, 11 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h index 9b083448814d..5bd127727d8e 100644 --- a/drivers/misc/ibmasm/ibmasm.h +++ b/drivers/misc/ibmasm/ibmasm.h @@ -211,7 +211,7 @@ void ibmasmfs_unregister(void); void ibmasmfs_add_sp(struct service_processor *sp); /* uart */ -#ifdef CONFIG_SERIAL_8250 +#if IS_ENABLED(CONFIG_SERIAL_8250) void ibmasm_register_uart(struct service_processor *sp); void ibmasm_unregister_uart(struct service_processor *sp); #else diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h index 2689375ae5da..262d6ef8df7c 100644 --- a/drivers/usb/chipidea/otg_fsm.h +++ b/drivers/usb/chipidea/otg_fsm.h @@ -62,7 +62,7 @@ /* SSEND time before SRP */ #define TB_SSEND_SRP (1500) /* minimum 1.5 sec, section:5.1.2 */ -#ifdef CONFIG_USB_OTG_FSM +#if IS_ENABLED(CONFIG_USB_OTG_FSM) int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci); int ci_otg_fsm_work(struct ci_hdrc *ci); diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 5f0937609465..23f961a8fb92 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h @@ -485,7 +485,7 @@ static inline int logfs_get_sb_bdev(struct logfs_super *s, #endif /* dev_mtd.c */ -#ifdef CONFIG_MTD +#if IS_ENABLED(CONFIG_MTD) int logfs_get_sb_mtd(struct logfs_super *s, int mtdnr); #else static inline int logfs_get_sb_mtd(struct logfs_super *s, int mtdnr) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 01df30af4d4a..2c47f9c305aa 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -372,10 +372,14 @@ endif # -objs := # or # -y := +# or +# -m := +# The -m syntax only works if is a module link_multi_deps = \ $(filter $(addprefix $(obj)/, \ $($(subst $(obj)/,,$(@:.o=-objs))) \ -$($(subst $(obj)/,,$(@:.o=-y)))), $^) +$($(subst $(obj)/,,$(@:.o=-y))) \ +$($(subst $(obj)/,,$(@:.o=-m)))), $^) quiet_cmd_link_multi-y = LD $@ cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis) @@ -390,7 +394,7 @@ $(call multi_depend, $(multi-used-y), .o, -objs -y) $(multi-used-m): FORCE $(call if_changed,link_multi-m) @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod) -$(call multi_depend, $(multi-used-m), .o, -objs -y) +$(call multi_depend, $(multi-used-m), .o, -objs -y -m) targets += $(multi-used-y) $(multi-used-m) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 79e86613712f..e18957b7a830 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -48,7 +48,7 @@ subdir-ym := $(sort $(subdir-y) $(subdir-m)) # if $(foo-objs) exists, foo.o is a composite object multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) -multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) +multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))), $(m)))) multi-used := $(multi-used-y) $(multi-used-m) single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m))) @@ -67,7 +67,7 @@ obj-dirs := $(dir $(multi-objs) $(obj-y)) # Replace multi-part objects by their individual parts, look at local dir only real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y) -real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) +real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m))) # Add subdir path -- cgit v1.2.3 From 4c835b57b8de88aef8446867701034128a8a3522 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Wed, 18 Nov 2015 19:07:15 +0100 Subject: fixdep: constify strrcmp arguments strrcmp only performs read access to the memory addressed by its arguments so make them const pointers. Signed-off-by: Nicolas Iooss Signed-off-by: Michal Marek --- scripts/basic/fixdep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index c68fd61fdc42..5b327c67a828 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -251,7 +251,7 @@ static void parse_config_file(const char *map, size_t len) } /* test is s ends in sub */ -static int strrcmp(char *s, char *sub) +static int strrcmp(const char *s, const char *sub) { int slen = strlen(s); int sublen = strlen(sub); -- cgit v1.2.3 From a78f70e8d65e88b9f631d073f68cb26dcd746298 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 9 Dec 2015 15:08:21 +0100 Subject: genksyms: Handle string literals with spaces in reference files The reference files use spaces to separate tokens, however, we must preserve spaces inside string literals. Currently the only case in the tree is struct edac_raw_error_desc in : $ KBUILD_SYMTYPES=1 make -s drivers/edac/amd64_edac.symtypes $ mv drivers/edac/amd64_edac.{symtypes,symref} $ KBUILD_SYMTYPES=1 make -s drivers/edac/amd64_edac.symtypes drivers/edac/amd64_edac.c:527: warning: amd64_get_dram_hole_info: modversion changed because of changes in struct edac_raw_error_desc Signed-off-by: Michal Marek --- scripts/genksyms/genksyms.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 88632df4381b..dafaf96e0a34 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -423,13 +423,15 @@ static struct string_list *read_node(FILE *f) struct string_list node = { .string = buffer, .tag = SYM_NORMAL }; - int c; + int c, in_string = 0; while ((c = fgetc(f)) != EOF) { - if (c == ' ') { + if (!in_string && c == ' ') { if (node.string == buffer) continue; break; + } else if (c == '"') { + in_string = !in_string; } else if (c == '\n') { if (node.string == buffer) return NULL; -- cgit v1.2.3 From 74dba80913775c78a1e03221c9ea51027a8b7bcf Mon Sep 17 00:00:00 2001 From: Markus Mayer Date: Wed, 9 Dec 2015 14:56:12 -0800 Subject: kconfig: allow kconfig to handle longer path names The current (arbitrary) limit of 128 characters for path names has proven too short for Android builds, as longer path names are used there. Change conf.c, so it can handle path lengths up to PATH_MAX characters. Signed-off-by: Markus Mayer Signed-off-by: Michal Marek --- scripts/kconfig/conf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 6c204318bc94..866369f10ff8 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -41,7 +42,7 @@ static int tty_stdio; static int valid_stdin = 1; static int sync_kconfig; static int conf_cnt; -static char line[128]; +static char line[PATH_MAX]; static struct menu *rootEntry; static void print_help(struct menu *menu) @@ -109,7 +110,7 @@ static int conf_askvalue(struct symbol *sym, const char *def) /* fall through */ case oldaskconfig: fflush(stdout); - xfgets(line, 128, stdin); + xfgets(line, sizeof(line), stdin); if (!tty_stdio) printf("\n"); return 1; @@ -311,7 +312,7 @@ static int conf_choice(struct menu *menu) /* fall through */ case oldaskconfig: fflush(stdout); - xfgets(line, 128, stdin); + xfgets(line, sizeof(line), stdin); strip(line); if (line[0] == '?') { print_help(menu); -- cgit v1.2.3 From aab24a897cfba9dd371f6aac45dbcdae0b23def6 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Fri, 1 Jan 2016 17:34:05 +0100 Subject: kconfig: return 'false' instead of 'no' in bool function menu_is_visible() is a bool function and should use boolean return values. "no" is a tristate value which happens to also have a value of 0, but we should nevertheless use the right symbol for it. This is a very minor cleanup with no semantic change. Fixes: 86e187ff9 ("kconfig: add an option to determine a menu's visibility") Cc: Arnaud Lacombe Cc: Mauro Carvalho Chehab Signed-off-by: Vegard Nossum Signed-off-by: Michal Marek --- scripts/kconfig/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index b05cc3d4a9be..aed678e8a777 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -477,7 +477,7 @@ bool menu_is_visible(struct menu *menu) if (menu->visibility) { if (expr_calc_value(menu->visibility) == no) - return no; + return false; } sym = menu->sym; -- cgit v1.2.3 From d2fb5aeda926307e4d95e3e824146aee9943de59 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 14 Oct 2015 09:45:52 +0200 Subject: tags: Treat header files as C code This allows to apply the same patters to both source and header files. The effect is mostly visible in the case of DECLARE_BITMAP, but there are small gains all over the place. There is also lots of random changes in the diff, I believe this is simply because there are still lots of unexpanded macros in the code and the C and C++ parsers fail and recover at different points. Also, qconf.h is parsed as C, but that's a negligible regression. Signed-off-by: Michal Marek --- scripts/tags.sh | 66 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index f69fa0c87312..25e30c30d1ad 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -165,42 +165,42 @@ exuberant() -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL,ACPI_EXPORT_SYMBOL \ -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \ -I static,const \ - --extra=+f --c-kinds=+px \ + --extra=+f --c-kinds=+px --langmap=c:+.h \ --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ --regex-c='/^COMPAT_SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/compat_sys_\1/' \ - --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ - --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1_rcuidle/' \ - --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ - --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1_rcuidle/' \ - --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ - --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ - --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ - --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ - --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ - --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ - --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ - --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ - --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ - --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ - --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ - --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ - --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ - --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ - --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ - --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ - --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ - --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ - --regex-c++='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \ - --regex-c++='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \ - --regex-c++='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/'\ - --regex-c++='/DEF_MMIO_(IN|OUT)_(X|D)\(([^,]*),\s*[^)]*\)/\3/' \ - --regex-c++='/DEBUGGER_BOILERPLATE\(([^,]*)\)/\1/' \ - --regex-c++='/DEF_PCI_AC_(NO)?RET\(([^,]*),.*/\2/' \ + --regex-c='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ + --regex-c='/^TRACE_EVENT\(([^,)]*).*/trace_\1_rcuidle/' \ + --regex-c='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ + --regex-c='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1_rcuidle/' \ + --regex-c='/PAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex-c='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex-c='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex-c='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex-c='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex-c='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex-c='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex-c='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex-c='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex-c='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex-c='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex-c='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ + --regex-c='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex-c='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ + --regex-c='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ + --regex-c='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ + --regex-c='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ + --regex-c='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ + --regex-c='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ + --regex-c='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \ + --regex-c='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \ + --regex-c='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/'\ + --regex-c='/DEF_MMIO_(IN|OUT)_(X|D)\(([^,]*),\s*[^)]*\)/\3/' \ + --regex-c='/DEBUGGER_BOILERPLATE\(([^,]*)\)/\1/' \ + --regex-c='/DEF_PCI_AC_(NO)?RET\(([^,]*),.*/\2/' \ --regex-c='/PCI_OP_READ\((\w*).*[1-4]\)/pci_bus_read_config_\1/' \ --regex-c='/PCI_OP_WRITE\((\w*).*[1-4]\)/pci_bus_write_config_\1/' \ --regex-c='/DEFINE_(MUTEX|SEMAPHORE|SPINLOCK)\((\w*)/\2/v/' \ -- cgit v1.2.3 From c26206f23a19af299540880ccf80e5a7af0f7db6 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 14 Oct 2015 10:55:04 +0200 Subject: tags: Fix erroneous pattern match in a comment Apparently, ctags applies the rules before deleting comments: ctags: Warning: include/linux/completion.h:22: null expansion of name pattern "\2" Work around this particular case by requiring the group to contain at least one character. Leave the other patters as they are, until a better solution is found. Signed-off-by: Michal Marek --- scripts/tags.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index 25e30c30d1ad..2263f35be490 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -205,7 +205,7 @@ exuberant() --regex-c='/PCI_OP_WRITE\((\w*).*[1-4]\)/pci_bus_write_config_\1/' \ --regex-c='/DEFINE_(MUTEX|SEMAPHORE|SPINLOCK)\((\w*)/\2/v/' \ --regex-c='/DEFINE_(RAW_SPINLOCK|RWLOCK|SEQLOCK)\((\w*)/\2/v/' \ - --regex-c='/DECLARE_(RWSEM|COMPLETION)\((\w*)/\2/v/' \ + --regex-c='/DECLARE_(RWSEM|COMPLETION)\((\w+)/\2/v/' \ --regex-c='/DECLARE_BITMAP\((\w*)/\1/v/' \ --regex-c='/(^|\s)(|L|H)LIST_HEAD\((\w*)/\3/v/' \ --regex-c='/(^|\s)RADIX_TREE\((\w*)/\2/v/' \ -- cgit v1.2.3 From a281b8569e9eb4beb1651c92145271555ba05f0c Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 14 Oct 2015 11:17:13 +0200 Subject: tags: Process Kconfig files in a single pass Signed-off-by: Michal Marek --- scripts/tags.sh | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index 2263f35be490..b97d687784d5 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -220,10 +220,7 @@ exuberant() all_kconfigs | xargs $1 -a \ --langdef=kconfig --language-force=kconfig \ - --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/' - - all_kconfigs | xargs $1 -a \ - --langdef=kconfig --language-force=kconfig \ + --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/' \ --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/CONFIG_\2/' all_defconfigs | xargs -r $1 -a \ @@ -271,9 +268,7 @@ emacs() --regex='/[^#]*DEFINE_HASHTABLE(\([^,)]*\)/\1/' all_kconfigs | xargs $1 -a \ - --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' - - all_kconfigs | xargs $1 -a \ + --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' \ --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/CONFIG_\3/' all_defconfigs | xargs -r $1 -a \ -- cgit v1.2.3 From ab9ca615f5f4053417cba464015bf2d7334a2371 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 15 Oct 2015 11:14:02 +0200 Subject: tags: Do not try to index defconfigs The defconfig files are in predictable locations, so there is no need to index them. Plus, the script was only looking for files named 'defconfig', which only works on a few architectures nowadays. Signed-off-by: Michal Marek --- scripts/tags.sh | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index b97d687784d5..e23427b6600a 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -134,11 +134,6 @@ all_kconfigs() find_other_sources 'Kconfig*' } -all_defconfigs() -{ - find_sources $ALLSOURCE_ARCHS "defconfig" -} - docscope() { (echo \-k; echo \-q; all_target_sources) > cscope.files @@ -222,10 +217,6 @@ exuberant() --langdef=kconfig --language-force=kconfig \ --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/' \ --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/CONFIG_\2/' - - all_defconfigs | xargs -r $1 -a \ - --langdef=dotconfig --language-force=dotconfig \ - --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' } emacs() @@ -270,9 +261,6 @@ emacs() all_kconfigs | xargs $1 -a \ --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' \ --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/CONFIG_\3/' - - all_defconfigs | xargs -r $1 -a \ - --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/' } xtags() -- cgit v1.2.3 From a1ccdb63b5535dc3446b0a9efc6d97aca82c72ef Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 15 Oct 2015 15:12:51 +0200 Subject: tags: Drop the _PE rule We are not indexing the userspace tools, so the rules only match some false positives in the kernel code. Signed-off-by: Michal Marek --- scripts/tags.sh | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index e23427b6600a..14abf81188b5 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -189,7 +189,6 @@ exuberant() --regex-c='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ --regex-c='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ --regex-c='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ - --regex-c='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ --regex-c='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \ --regex-c='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \ --regex-c='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/'\ @@ -253,7 +252,6 @@ emacs() --regex='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \ --regex='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \ --regex='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/' \ - --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' \ --regex='/PCI_OP_READ(\([a-z]*[a-z]\).*[1-4])/pci_bus_read_config_\1/' \ --regex='/PCI_OP_WRITE(\([a-z]*[a-z]\).*[1-4])/pci_bus_write_config_\1/'\ --regex='/[^#]*DEFINE_HASHTABLE(\([^,)]*\)/\1/' -- cgit v1.2.3 From 93209d65c1d38f86ffb3f61a1214130b581a9709 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 14 Oct 2015 11:48:06 +0200 Subject: tags: Unify emacs and exuberant rules The emacs rules were constantly lagging behind the exuberant ones. Use a single set of rules for both, to make the script easier to maintain. The language understood by both tools is basic regular expression with some limitations, which are documented in a comment. To be able to store the rules in an array and easily iterate over it, the script requires bash now. In the exuberant case, the change fixes some false matches in and also some too greedy matches in the arguments of the DECLARE_*/DEFINE_* macros. In the emacs case, several previously not working rules are matching now. Tested with these versions of the tools: Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert etags (GNU Emacs 24.5) Signed-off-by: Michal Marek --- scripts/tags.sh | 202 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 109 insertions(+), 93 deletions(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index 14abf81188b5..bcc1d8cb142b 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Generate tags or cscope files # Usage tags.sh # @@ -145,8 +145,108 @@ dogtags() all_target_sources | gtags -i -f - } +# Basic regular expressions with an optional /kind-spec/ for ctags and +# the following limitations: +# - No regex modifiers +# - Use \{0,1\} instead of \?, because etags expects an unescaped ? +# - \s is not working with etags, use a space or [ \t] +# - \w works, but does not match underscores in etags +# - etags regular expressions have to match at the start of a line; +# a ^[^#] is prepended by setup_regex unless an anchor is already present +regex_asm=( + '/^\(ENTRY\|_GLOBAL\)(\([[:alnum:]_\\]*\)).*/\2/' +) +regex_c=( + '/^SYSCALL_DEFINE[0-9](\([[:alnum:]_]*\).*/sys_\1/' + '/^COMPAT_SYSCALL_DEFINE[0-9](\([[:alnum:]_]*\).*/compat_sys_\1/' + '/^TRACE_EVENT(\([[:alnum:]_]*\).*/trace_\1/' + '/^TRACE_EVENT(\([[:alnum:]_]*\).*/trace_\1_rcuidle/' + '/^DEFINE_EVENT([^,)]*, *\([[:alnum:]_]*\).*/trace_\1/' + '/^DEFINE_EVENT([^,)]*, *\([[:alnum:]_]*\).*/trace_\1_rcuidle/' + '/^PAGEFLAG(\([[:alnum:]_]*\).*/Page\1/' + '/^PAGEFLAG(\([[:alnum:]_]*\).*/SetPage\1/' + '/^PAGEFLAG(\([[:alnum:]_]*\).*/ClearPage\1/' + '/^TESTSETFLAG(\([[:alnum:]_]*\).*/TestSetPage\1/' + '/^TESTPAGEFLAG(\([[:alnum:]_]*\).*/Page\1/' + '/^SETPAGEFLAG(\([[:alnum:]_]*\).*/SetPage\1/' + '/\<__SETPAGEFLAG(\([[:alnum:]_]*\).*/__SetPage\1/' + '/\ Date: Fri, 8 Jan 2016 20:44:04 +0000 Subject: kconfig: fix qconf segfault by deleting heap objects On Debian stable (qt-4.8.6) 'make xconfig' intermittently fails due to qconf segfaulting at exit time in QXcbEventReader. The cause of this is destructors on the heap objects never being called, so fix this by properly deleting the heap objects before exit. Signed-off-by: Chris Bainbridge Signed-off-by: Michal Marek --- scripts/kconfig/qconf.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 91b7e6fbc364..fc5555992220 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1863,6 +1863,8 @@ int main(int ac, char** av) configSettings->endGroup(); delete configSettings; + delete v; + delete configApp; return 0; } -- cgit v1.2.3 From 7599ea8b4e25fd8dea26cb64f100cf265d1e6bf3 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jan 2016 14:24:18 +0000 Subject: kbuild: Demote 'sign-compare' warning to W=2 Ideally, a kernel compile with W=1 enabled should complete cleanly; however, when we run one currently we are presented with ~25k warnings. 'sign-compare' accounts for ~22k of those ~25k. In this patch we're demoting 'sign-compare' warnings to W=2, with a view to fixing the remaining 3k W=1 warnings required for a clean build. Arnd adds: "As per our discussion, I'd add that this was inadvertedly introduced by Behan when he moved the clang specific warnings into an ifdef block and did not notice that -Wsign-compare was interpreted by both gcc and clang. Earlier, it was introduced in just the same way by Jan-Simon as part of 3d3d6b847420 ("kbuild: LLVMLinux: Adapt warnings for compilation with clang")." Acked-by: Arnd Bergmann Fixes: 26ea6bb1fef0 ("kbuild, LLVMLinux: Supress warnings unless W=1-3") Signed-off-by: Lee Jones Signed-off-by: Michal Marek --- scripts/Makefile.extrawarn | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 4efedcbe4165..f9e47a70509c 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -25,6 +25,7 @@ warning-1 += -Wold-style-definition warning-1 += $(call cc-option, -Wmissing-include-dirs) warning-1 += $(call cc-option, -Wunused-but-set-variable) warning-1 += $(call cc-disable-warning, missing-field-initializers) +warning-1 += $(call cc-disable-warning, sign-compare) warning-2 := -Waggregate-return warning-2 += -Wcast-align @@ -33,6 +34,7 @@ warning-2 += -Wnested-externs warning-2 += -Wshadow warning-2 += $(call cc-option, -Wlogical-op) warning-2 += $(call cc-option, -Wmissing-field-initializers) +warning-2 += $(call cc-option, -Wsign-compare) warning-3 := -Wbad-function-cast warning-3 += -Wcast-qual -- cgit v1.2.3 From 3f984cb39907f87515d83657ecd471ae396a6c4a Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 7 Jan 2016 10:36:51 +0100 Subject: coccinelle: tests: unsigned value cannot be lesser than zero Unsigned expressions cannot be lesser than zero. Presence of comparisons 'unsigned (<|<=|>|>=) 0' often indicates a bug, usually wrong type of variable. The patch beside finding such comparisons tries to eliminate false positives, mainly by bypassing range checks. gcc can detect such comparisons also using -Wtype-limits switch, but it warns also in correct cases, making too much noise. Signed-off-by: Andrzej Hajda Acked-by: Julia Lawall Signed-off-by: Michal Marek --- .../tests/unsigned_lesser_than_zero.cocci | 75 ++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci b/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci new file mode 100644 index 000000000000..8fa5a3c7b784 --- /dev/null +++ b/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci @@ -0,0 +1,75 @@ +/// Unsigned expressions cannot be lesser than zero. Presence of +/// comparisons 'unsigned (<|<=|>|>=) 0' often indicates a bug, +/// usually wrong type of variable. +/// +/// To reduce number of false positives following tests have been added: +/// - parts of range checks are skipped, eg. "if (u < 0 || u > 15) ...", +/// developers prefer to keep such code, +/// - comparisons "<= 0" and "> 0" are performed only on results of +/// signed functions/macros, +/// - hardcoded list of signed functions/macros with always non-negative +/// result is used to avoid false positives difficult to detect by other ways +/// +// Confidence: Average +// Copyright: (C) 2015 Andrzej Hajda, Samsung Electronics Co., Ltd. GPLv2. +// URL: http://coccinelle.lip6.fr/ +// Options: --all-includes + +virtual context +virtual org +virtual report + +@r_cmp@ +position p; +typedef bool, u8, u16, u32, u64; +{unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long, + size_t, bool, u8, u16, u32, u64} v; +expression e; +@@ + + \( v = e \| &v \) + ... + (\( v@p < 0 \| v@p <= 0 \| v@p >= 0 \| v@p > 0 \)) + +@r@ +position r_cmp.p; +typedef s8, s16, s32, s64; +{char, short, int, long, long long, ssize_t, s8, s16, s32, s64} vs; +expression c, e, v; +identifier f !~ "^(ata_id_queue_depth|btrfs_copy_from_user|dma_map_sg|dma_map_sg_attrs|fls|fls64|gameport_time|get_write_extents|nla_len|ntoh24|of_flat_dt_match|of_get_child_count|uart_circ_chars_pending|[A-Z0-9_]+)$"; +@@ + +( + v = f(...)@vs; + ... when != v = e; +* (\( v@p <=@e 0 \| v@p >@e 0 \)) + ... when any +| +( + (\( v@p < 0 \| v@p <= 0 \)) || ... || (\( v >= c \| v > c \)) +| + (\( v >= c \| v > c \)) || ... || (\( v@p < 0 \| v@p <= 0 \)) +| + (\( v@p >= 0 \| v@p > 0 \)) && ... && (\( v < c \| v <= c \)) +| + ((\( v < c \| v <= c \) && ... && \( v@p >= 0 \| v@p > 0 \))) +| +* (\( v@p <@e 0 \| v@p >=@e 0 \)) +) +) + +@script:python depends on org@ +p << r_cmp.p; +e << r.e; +@@ + +msg = "WARNING: Unsigned expression compared with zero: %s" % (e) +coccilib.org.print_todo(p[0], msg) + +@script:python depends on report@ +p << r_cmp.p; +e << r.e; +@@ + +msg = "WARNING: Unsigned expression compared with zero: %s" % (e) +coccilib.report.print_report(p[0], msg) -- cgit v1.2.3 From 402c2553a24729688ba32453a9f6889e12754147 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 4 Jan 2016 09:39:01 +0200 Subject: checkpatch.pl: add missing memory barriers SMP-only barriers were missing in checkpatch.pl Refactor code slightly to make adding more variants easier. Signed-off-by: Michael S. Tsirkin Acked-by: Julian Calaby Acked-by: Joe Perches Acked-by: Peter Zijlstra (Intel) --- scripts/checkpatch.pl | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 2b3c22808c3b..94b4e33fa532 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5116,7 +5116,27 @@ sub process { } } # check for memory barriers without a comment. - if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) { + + my $barriers = qr{ + mb| + rmb| + wmb| + read_barrier_depends + }x; + my $barrier_stems = qr{ + mb__before_atomic| + mb__after_atomic| + store_release| + load_acquire| + store_mb| + (?:$barriers) + }x; + my $all_barriers = qr{ + (?:$barriers)| + smp_(?:$barrier_stems) + }x; + + if ($line =~ /\b(?:$all_barriers)\s*\(/) { if (!ctx_has_comment($first_line, $linenr)) { WARN("MEMORY_BARRIER", "memory barrier without comment\n" . $herecurr); -- cgit v1.2.3 From f4073b0f6e11a5436d1162c623401c8f2f7cf783 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 4 Jan 2016 09:54:51 +0200 Subject: checkpatch: check for __smp outside barrier.h Introduction of __smp barriers cleans up a bunch of duplicate code, but it gives people an additional handle onto a "new" set of barriers - just because they're prefixed with __* unfortunately doesn't stop anyone from using it (as happened with other arch stuff before.) Add a checkpatch test so it will trigger a warning. Reported-by: Russell King Signed-off-by: Michael S. Tsirkin Acked-by: Julian Calaby Acked-by: Joe Perches Acked-by: Peter Zijlstra (Intel) --- scripts/checkpatch.pl | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 94b4e33fa532..25476c29bb18 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5143,6 +5143,16 @@ sub process { } } + my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; + + if ($realfile !~ m@^include/asm-generic/@ && + $realfile !~ m@/barrier\.h$@ && + $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && + $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { + WARN("MEMORY_BARRIER", + "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); + } + # check for waitqueue_active without a comment. if ($line =~ /\bwaitqueue_active\s*\(/) { if (!ctx_has_comment($first_line, $linenr)) { -- cgit v1.2.3 From 43e361f23c49dbddf74f56ddf6cdd85c5dbff6da Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 4 Jan 2016 10:00:10 +0200 Subject: checkpatch: add virt barriers Add virt_ barriers to list of barriers to check for presence of a comment. Signed-off-by: Michael S. Tsirkin Acked-by: Julian Calaby Acked-by: Joe Perches Acked-by: Peter Zijlstra (Intel) --- scripts/checkpatch.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 25476c29bb18..c7bf1aa2eeb3 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5133,7 +5133,8 @@ sub process { }x; my $all_barriers = qr{ (?:$barriers)| - smp_(?:$barrier_stems) + smp_(?:$barrier_stems)| + virt_(?:$barrier_stems) }x; if ($line =~ /\b(?:$all_barriers)\s*\(/) { -- cgit v1.2.3 From 685eaade56c66c806dbe8102f12e2926cf4ec870 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Fri, 15 Jan 2016 16:52:10 -0800 Subject: page-flags: drop __TestClearPage*() helpers Nobody uses them. Signed-off-by: Kirill A. Shutemov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 10 +--------- scripts/tags.sh | 2 -- 2 files changed, 1 insertion(+), 11 deletions(-) (limited to 'scripts') diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 190f1915a097..7bc7fd9c4c5c 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -211,10 +211,6 @@ static inline int TestSetPage##uname(struct page *page) \ static inline int TestClearPage##uname(struct page *page) \ { return test_and_clear_bit(PG_##lname, &policy(page, 1)->flags); } -#define __TESTCLEARFLAG(uname, lname, policy) \ -static inline int __TestClearPage##uname(struct page *page) \ - { return __test_and_clear_bit(PG_##lname, &policy(page, 1)->flags); } - #define PAGEFLAG(uname, lname, policy) \ TESTPAGEFLAG(uname, lname, policy) \ SETPAGEFLAG(uname, lname, policy) \ @@ -247,9 +243,6 @@ static inline int TestSetPage##uname(struct page *page) { return 0; } #define TESTCLEARFLAG_FALSE(uname) \ static inline int TestClearPage##uname(struct page *page) { return 0; } -#define __TESTCLEARFLAG_FALSE(uname) \ -static inline int __TestClearPage##uname(struct page *page) { return 0; } - #define PAGEFLAG_FALSE(uname) TESTPAGEFLAG_FALSE(uname) \ SETPAGEFLAG_NOOP(uname) CLEARPAGEFLAG_NOOP(uname) @@ -331,10 +324,9 @@ PAGEFLAG(Unevictable, unevictable, PF_HEAD) PAGEFLAG(Mlocked, mlocked, PF_NO_TAIL) __CLEARPAGEFLAG(Mlocked, mlocked, PF_NO_TAIL) TESTSCFLAG(Mlocked, mlocked, PF_NO_TAIL) - __TESTCLEARFLAG(Mlocked, mlocked, PF_NO_TAIL) #else PAGEFLAG_FALSE(Mlocked) __CLEARPAGEFLAG_NOOP(Mlocked) - TESTSCFLAG_FALSE(Mlocked) __TESTCLEARFLAG_FALSE(Mlocked) + TESTSCFLAG_FALSE(Mlocked) #endif #ifdef CONFIG_ARCH_USES_PG_UNCACHED diff --git a/scripts/tags.sh b/scripts/tags.sh index 262889046703..76f131ebc192 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -193,7 +193,6 @@ exuberant() --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ --regex-c++='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \ --regex-c++='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \ @@ -260,7 +259,6 @@ emacs() --regex='/CLEARPAGEFLAG_NOOP(\([^,)]*\).*/ClearPage\1/' \ --regex='/__CLEARPAGEFLAG_NOOP(\([^,)]*\).*/__ClearPage\1/' \ --regex='/TESTCLEARFLAG_FALSE(\([^,)]*\).*/TestClearPage\1/' \ - --regex='/__TESTCLEARFLAG_FALSE(\([^,)]*\).*/__TestClearPage\1/' \ --regex='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \ --regex='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \ --regex='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/' \ -- cgit v1.2.3 From be17bddc6907f65b0a9f0ff77200a6d403ac41d1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 20 Jan 2016 14:58:24 -0800 Subject: scripts/get_maintainer.pl: handle file names beginning with ./ The problem is that get_maintainer.pl doesn't work if you have a ./ prefix on the filename. For example, if you type: ./scripts/get_maintainer.pl -f ./drivers/usb/usb-skeleton.c then the current code only includes LKML and people from the git log, it doesn't include Greg or the linux-usb list. Reported-by: Dan Carpenter Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts') diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index cab641a12dd5..1873421f2305 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -16,7 +16,9 @@ my $P = $0; my $V = '0.26'; use Getopt::Long qw(:config no_auto_abbrev); +use Cwd; +my $cur_path = fastgetcwd() . '/'; my $lk_path = "./"; my $email = 1; my $email_usename = 1; @@ -429,6 +431,8 @@ foreach my $file (@ARGV) { } } if ($from_filename) { + $file =~ s/^\Q${cur_path}\E//; #strip any absolute path + $file =~ s/^\Q${lk_path}\E//; #or the path to the lk tree push(@files, $file); if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) { open(my $f, '<', $file) -- cgit v1.2.3 From 938224b5e596c1c30d968ffd927a578ea7c4f45b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 20 Jan 2016 14:59:15 -0800 Subject: checkpatch: warn when casting constants to c90 int or longer types Linus Torvalds wrote: > I can't but help to react that this: > #define IOMMU_ERROR_CODE (~(unsigned long) 0) > Not that this *matters*, but it's a bit odd to have to cast constants > to perfectly regular C types. So add a test that looks for constants that are cast to standard C90 int or longer types and suggest using C90 "6.4.4.1 Integer constants" integer-suffixes instead. Miscellanea: o Add a --fix option too Signed-off-by: Joe Perches Suggested-by: Andrew Morton Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index c7bf1aa2eeb3..86457062db29 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -433,6 +433,28 @@ our @typeList = ( qr{${Ident}_handler_fn}, @typeListMisordered, ); + +our $C90_int_types = qr{(?x: + long\s+long\s+int\s+(?:un)?signed| + long\s+long\s+(?:un)?signed\s+int| + long\s+long\s+(?:un)?signed| + (?:(?:un)?signed\s+)?long\s+long\s+int| + (?:(?:un)?signed\s+)?long\s+long| + int\s+long\s+long\s+(?:un)?signed| + int\s+(?:(?:un)?signed\s+)?long\s+long| + + long\s+int\s+(?:un)?signed| + long\s+(?:un)?signed\s+int| + long\s+(?:un)?signed| + (?:(?:un)?signed\s+)?long\s+int| + (?:(?:un)?signed\s+)?long| + int\s+long\s+(?:un)?signed| + int\s+(?:(?:un)?signed\s+)?long| + + int\s+(?:un)?signed| + (?:(?:un)?signed\s+)?int +)}; + our @typeListFile = (); our @typeListWithAttr = ( @typeList, @@ -5272,6 +5294,26 @@ sub process { } } +# check for cast of C90 native int or longer types constants + if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { + my $cast = $1; + my $const = $2; + if (WARN("TYPECAST_INT_CONSTANT", + "Unnecessary typecast of c90 int constant\n" . $herecurr) && + $fix) { + my $suffix = ""; + my $newconst = $const; + $newconst =~ s/${Int_type}$//; + $suffix .= 'U' if ($cast =~ /\bunsigned\b/); + if ($cast =~ /\blong\s+long\b/) { + $suffix .= 'LL'; + } elsif ($cast =~ /\blong\b/) { + $suffix .= 'L'; + } + $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; + } + } + # check for sizeof(&) if ($line =~ /\bsizeof\s*\(\s*\&/) { WARN("SIZEOF_ADDRESS", -- cgit v1.2.3 From 62e15a6daab0f6b3e8233e976201bce9faecaaf7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 20 Jan 2016 14:59:18 -0800 Subject: checkpatch: improve macros with flow control test The current test excludes any macro with ## concatenation from being reported with hidden flow control. Some macros are used with return or goto statements along with ##args or ##__VA_ARGS__. A somewhat common case is a logging macro like pr_info(fmt, ...) then a return or goto statement. Check the concatenated variable for args or __VA_ARGS__ and allow those macros to also be reported when they contain a return or goto. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 86457062db29..77b293d5ce4f 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4539,7 +4539,7 @@ sub process { #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); - $has_arg_concat = 1 if ($ctx =~ /\#\#/); + $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; $dstat =~ s/$;//g; -- cgit v1.2.3 From 6b10df4257367dd0ead49f88df473972c00a8b5c Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 20 Jan 2016 14:59:21 -0800 Subject: checkpatch: fix a number of COMPLEX_MACRO false positives A simple search over the kernel souce displays a number of correctly defined multiline macro, which generally are used as an array element initializer: % find ../linux -type f | xargs grep -B1 -H '^[:space]*\[.*\\$' However checkpatch.pl unexpectedly complains about all these macro definitions: % ./scripts/checkpatch.pl --types COMPLEX_MACRO -f include/linux/perf/arm_pmu.h ERROR: Macros with complex values should be enclosed in parentheses +#define PERF_MAP_ALL_UNSUPPORTED \ + [0 ... PERF_COUNT_HW_MAX - 1] = HW_OP_UNSUPPORTED The change intends to fix this type of false positives by flattening only array members and skipping array element designators. Signed-off-by: Vladimir Zapolskiy Acked-by: Joe Perches Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 77b293d5ce4f..0147c91fa549 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4550,7 +4550,7 @@ sub process { # Flatten any parentheses and braces while ($dstat =~ s/\([^\(\)]*\)/1/ || $dstat =~ s/\{[^\{\}]*\}/1/ || - $dstat =~ s/\[[^\[\]]*\]/1/) + $dstat =~ s/.\[[^\[\]]*\]/1/) { } @@ -4570,7 +4570,8 @@ sub process { union| struct| \.$Ident\s*=\s*| - ^\"|\"$ + ^\"|\"$| + ^\[ }x; #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; if ($dstat ne '' && -- cgit v1.2.3 From c6d308534aef6c99904bf5862066360ae067abc4 Mon Sep 17 00:00:00 2001 From: Andrey Ryabinin Date: Wed, 20 Jan 2016 15:00:55 -0800 Subject: UBSAN: run-time undefined behavior sanity checker UBSAN uses compile-time instrumentation to catch undefined behavior (UB). Compiler inserts code that perform certain kinds of checks before operations that could cause UB. If check fails (i.e. UB detected) __ubsan_handle_* function called to print error message. So the most of the work is done by compiler. This patch just implements ubsan handlers printing errors. GCC has this capability since 4.9.x [1] (see -fsanitize=undefined option and its suboptions). However GCC 5.x has more checkers implemented [2]. Article [3] has a bit more details about UBSAN in the GCC. [1] - https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Debugging-Options.html [2] - https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html [3] - http://developerblog.redhat.com/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ Issues which UBSAN has found thus far are: Found bugs: * out-of-bounds access - 97840cb67ff5 ("netfilter: nfnetlink: fix insufficient validation in nfnetlink_bind") undefined shifts: * d48458d4a768 ("jbd2: use a better hash function for the revoke table") * 10632008b9e1 ("clockevents: Prevent shift out of bounds") * 'x << -1' shift in ext4 - http://lkml.kernel.org/r/<5444EF21.8020501@samsung.com> * undefined rol32(0) - http://lkml.kernel.org/r/<1449198241-20654-1-git-send-email-sasha.levin@oracle.com> * undefined dirty_ratelimit calculation - http://lkml.kernel.org/r/<566594E2.3050306@odin.com> * undefined roundown_pow_of_two(0) - http://lkml.kernel.org/r/<1449156616-11474-1-git-send-email-sasha.levin@oracle.com> * [WONTFIX] undefined shift in __bpf_prog_run - http://lkml.kernel.org/r/ WONTFIX here because it should be fixed in bpf program, not in kernel. signed overflows: * 32a8df4e0b33f ("sched: Fix odd values in effective_load() calculations") * mul overflow in ntp - http://lkml.kernel.org/r/<1449175608-1146-1-git-send-email-sasha.levin@oracle.com> * incorrect conversion into rtc_time in rtc_time64_to_tm() - http://lkml.kernel.org/r/<1449187944-11730-1-git-send-email-sasha.levin@oracle.com> * unvalidated timespec in io_getevents() - http://lkml.kernel.org/r/ * [NOTABUG] signed overflow in ktime_add_safe() - http://lkml.kernel.org/r/ [akpm@linux-foundation.org: fix unused local warning] [akpm@linux-foundation.org: fix __int128 build woes] Signed-off-by: Andrey Ryabinin Cc: Peter Zijlstra Cc: Sasha Levin Cc: Randy Dunlap Cc: Rasmus Villemoes Cc: Jonathan Corbet Cc: Michal Marek Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Yury Gribov Cc: Dmitry Vyukov Cc: Konstantin Khlebnikov Cc: Kostya Serebryany Cc: Johannes Berg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ubsan.txt | 84 +++++++ Makefile | 3 +- arch/x86/Kconfig | 1 + arch/x86/boot/Makefile | 1 + arch/x86/boot/compressed/Makefile | 1 + arch/x86/entry/vdso/Makefile | 1 + arch/x86/realmode/rm/Makefile | 1 + drivers/firmware/efi/libstub/Makefile | 1 + include/linux/sched.h | 3 + lib/Kconfig.debug | 2 + lib/Kconfig.ubsan | 29 +++ lib/Makefile | 3 + lib/ubsan.c | 456 ++++++++++++++++++++++++++++++++++ lib/ubsan.h | 84 +++++++ mm/kasan/Makefile | 1 + scripts/Makefile.lib | 6 + scripts/Makefile.ubsan | 17 ++ 17 files changed, 693 insertions(+), 1 deletion(-) create mode 100644 Documentation/ubsan.txt create mode 100644 lib/Kconfig.ubsan create mode 100644 lib/ubsan.c create mode 100644 lib/ubsan.h create mode 100644 scripts/Makefile.ubsan (limited to 'scripts') diff --git a/Documentation/ubsan.txt b/Documentation/ubsan.txt new file mode 100644 index 000000000000..f58215ef5797 --- /dev/null +++ b/Documentation/ubsan.txt @@ -0,0 +1,84 @@ +Undefined Behavior Sanitizer - UBSAN + +Overview +-------- + +UBSAN is a runtime undefined behaviour checker. + +UBSAN uses compile-time instrumentation to catch undefined behavior (UB). +Compiler inserts code that perform certain kinds of checks before operations +that may cause UB. If check fails (i.e. UB detected) __ubsan_handle_* +function called to print error message. + +GCC has that feature since 4.9.x [1] (see -fsanitize=undefined option and +its suboptions). GCC 5.x has more checkers implemented [2]. + +Report example +--------------- + + ================================================================================ + UBSAN: Undefined behaviour in ../include/linux/bitops.h:110:33 + shift exponent 32 is to large for 32-bit type 'unsigned int' + CPU: 0 PID: 0 Comm: swapper Not tainted 4.4.0-rc1+ #26 + 0000000000000000 ffffffff82403cc8 ffffffff815e6cd6 0000000000000001 + ffffffff82403cf8 ffffffff82403ce0 ffffffff8163a5ed 0000000000000020 + ffffffff82403d78 ffffffff8163ac2b ffffffff815f0001 0000000000000002 + Call Trace: + [] dump_stack+0x45/0x5f + [] ubsan_epilogue+0xd/0x40 + [] __ubsan_handle_shift_out_of_bounds+0xeb/0x130 + [] ? radix_tree_gang_lookup_slot+0x51/0x150 + [] _mix_pool_bytes+0x1e6/0x480 + [] ? dmi_walk_early+0x48/0x5c + [] add_device_randomness+0x61/0x130 + [] ? dmi_save_one_device+0xaa/0xaa + [] dmi_walk_early+0x48/0x5c + [] dmi_scan_machine+0x278/0x4b4 + [] ? vprintk_default+0x1a/0x20 + [] ? early_idt_handler_array+0x120/0x120 + [] setup_arch+0x405/0xc2c + [] ? early_idt_handler_array+0x120/0x120 + [] start_kernel+0x83/0x49a + [] ? early_idt_handler_array+0x120/0x120 + [] x86_64_start_reservations+0x2a/0x2c + [] x86_64_start_kernel+0x16b/0x17a + ================================================================================ + +Usage +----- + +To enable UBSAN configure kernel with: + + CONFIG_UBSAN=y + +and to check the entire kernel: + + CONFIG_UBSAN_SANITIZE_ALL=y + +To enable instrumentation for specific files or directories, add a line +similar to the following to the respective kernel Makefile: + + For a single file (e.g. main.o): + UBSAN_SANITIZE_main.o := y + + For all files in one directory: + UBSAN_SANITIZE := y + +To exclude files from being instrumented even if +CONFIG_UBSAN_SANITIZE_ALL=y, use: + + UBSAN_SANITIZE_main.o := n + and: + UBSAN_SANITIZE := n + +Detection of unaligned accesses controlled through the separate option - +CONFIG_UBSAN_ALIGNMENT. It's off by default on architectures that support +unaligned accesses (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y). One could +still enable it in config, just note that it will produce a lot of UBSAN +reports. + +References +---------- + +[1] - https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Debugging-Options.html +[2] - https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html diff --git a/Makefile b/Makefile index 7f4ac1ee4a2b..abfb3e8eb0b1 100644 --- a/Makefile +++ b/Makefile @@ -411,7 +411,7 @@ export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS -export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV CFLAGS_KASAN +export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV CFLAGS_KASAN CFLAGS_UBSAN export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL @@ -784,6 +784,7 @@ endif include scripts/Makefile.kasan include scripts/Makefile.extrawarn +include scripts/Makefile.ubsan # Add any arch overrides and user supplied CPPFLAGS, AFLAGS and CFLAGS as the # last assignments diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4a10ba9e95da..92b2a73162ee 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -31,6 +31,7 @@ config X86 select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_MMIO_FLUSH select ARCH_HAS_SG_CHAIN + select ARCH_HAS_UBSAN_SANITIZE_ALL select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI select ARCH_MIGHT_HAVE_PC_PARPORT diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 2ee62dba0373..bbe1a62efc02 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -60,6 +60,7 @@ clean-files += cpustr.h KBUILD_CFLAGS := $(USERINCLUDE) $(REALMODE_CFLAGS) -D_SETUP KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ GCOV_PROFILE := n +UBSAN_SANITIZE := n $(obj)/bzImage: asflags-y := $(SVGA_MODE) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 0a291cdfaf77..f9ce75d80101 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -33,6 +33,7 @@ KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector) KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ GCOV_PROFILE := n +UBSAN_SANITIZE :=n LDFLAGS := -m elf_$(UTS_MACHINE) LDFLAGS_vmlinux := -T diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile index 265c0ed68118..c854541d93ff 100644 --- a/arch/x86/entry/vdso/Makefile +++ b/arch/x86/entry/vdso/Makefile @@ -4,6 +4,7 @@ KBUILD_CFLAGS += $(DISABLE_LTO) KASAN_SANITIZE := n +UBSAN_SANITIZE := n VDSO64-$(CONFIG_X86_64) := y VDSOX32-$(CONFIG_X86_X32_ABI) := y diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index 2730d775ef9a..3e75fcf6b836 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile @@ -70,3 +70,4 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) $(REALMODE_CFLAGS) -D_SETUP -D_WAKEUP \ -I$(srctree)/arch/x86/boot KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ GCOV_PROFILE := n +UBSAN_SANITIZE := n diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 9c12e18031d5..aaf9c0bab42e 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -22,6 +22,7 @@ KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \ GCOV_PROFILE := n KASAN_SANITIZE := n +UBSAN_SANITIZE := n lib-y := efi-stub-helper.o diff --git a/include/linux/sched.h b/include/linux/sched.h index 61aa9bbea871..02dabf281b2f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1643,6 +1643,9 @@ struct task_struct { struct held_lock held_locks[MAX_LOCK_DEPTH]; gfp_t lockdep_reclaim_gfp; #endif +#ifdef CONFIG_UBSAN + unsigned int in_ubsan; +#endif /* journalling filesystem info */ void *journal_info; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index f75a33f29f6e..157220b9ff05 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1893,6 +1893,8 @@ source "samples/Kconfig" source "lib/Kconfig.kgdb" +source "lib/Kconfig.ubsan" + config ARCH_HAS_DEVMEM_IS_ALLOWED bool diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan new file mode 100644 index 000000000000..49518fb48cab --- /dev/null +++ b/lib/Kconfig.ubsan @@ -0,0 +1,29 @@ +config ARCH_HAS_UBSAN_SANITIZE_ALL + bool + +config UBSAN + bool "Undefined behaviour sanity checker" + help + This option enables undefined behaviour sanity checker + Compile-time instrumentation is used to detect various undefined + behaviours in runtime. Various types of checks may be enabled + via boot parameter ubsan_handle (see: Documentation/ubsan.txt). + +config UBSAN_SANITIZE_ALL + bool "Enable instrumentation for the entire kernel" + depends on UBSAN + depends on ARCH_HAS_UBSAN_SANITIZE_ALL + default y + help + This option activates instrumentation for the entire kernel. + If you don't enable this option, you have to explicitly specify + UBSAN_SANITIZE := y for the files/directories you want to check for UB. + +config UBSAN_ALIGNMENT + bool "Enable checking of pointers alignment" + depends on UBSAN + default y if !HAVE_EFFICIENT_UNALIGNED_ACCESS + help + This option enables detection of unaligned memory accesses. + Enabling this option on architectures that support unalligned + accesses may produce a lot of false positives. diff --git a/lib/Makefile b/lib/Makefile index b2a82e600987..2d4bc33d09b4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -209,3 +209,6 @@ quiet_cmd_build_OID_registry = GEN $@ clean-files += oid_registry_data.c obj-$(CONFIG_UCS2_STRING) += ucs2_string.o +obj-$(CONFIG_UBSAN) += ubsan.o + +UBSAN_SANITIZE_ubsan.o := n diff --git a/lib/ubsan.c b/lib/ubsan.c new file mode 100644 index 000000000000..8799ae5e2e42 --- /dev/null +++ b/lib/ubsan.c @@ -0,0 +1,456 @@ +/* + * UBSAN error reporting functions + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Andrey Ryabinin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ubsan.h" + +const char *type_check_kinds[] = { + "load of", + "store to", + "reference binding to", + "member access within", + "member call on", + "constructor call on", + "downcast of", + "downcast of" +}; + +#define REPORTED_BIT 31 + +#if (BITS_PER_LONG == 64) && defined(__BIG_ENDIAN) +#define COLUMN_MASK (~(1U << REPORTED_BIT)) +#define LINE_MASK (~0U) +#else +#define COLUMN_MASK (~0U) +#define LINE_MASK (~(1U << REPORTED_BIT)) +#endif + +#define VALUE_LENGTH 40 + +static bool was_reported(struct source_location *location) +{ + return test_and_set_bit(REPORTED_BIT, &location->reported); +} + +static void print_source_location(const char *prefix, + struct source_location *loc) +{ + pr_err("%s %s:%d:%d\n", prefix, loc->file_name, + loc->line & LINE_MASK, loc->column & COLUMN_MASK); +} + +static bool suppress_report(struct source_location *loc) +{ + return current->in_ubsan || was_reported(loc); +} + +static bool type_is_int(struct type_descriptor *type) +{ + return type->type_kind == type_kind_int; +} + +static bool type_is_signed(struct type_descriptor *type) +{ + WARN_ON(!type_is_int(type)); + return type->type_info & 1; +} + +static unsigned type_bit_width(struct type_descriptor *type) +{ + return 1 << (type->type_info >> 1); +} + +static bool is_inline_int(struct type_descriptor *type) +{ + unsigned inline_bits = sizeof(unsigned long)*8; + unsigned bits = type_bit_width(type); + + WARN_ON(!type_is_int(type)); + + return bits <= inline_bits; +} + +static s_max get_signed_val(struct type_descriptor *type, unsigned long val) +{ + if (is_inline_int(type)) { + unsigned extra_bits = sizeof(s_max)*8 - type_bit_width(type); + return ((s_max)val) << extra_bits >> extra_bits; + } + + if (type_bit_width(type) == 64) + return *(s64 *)val; + + return *(s_max *)val; +} + +static bool val_is_negative(struct type_descriptor *type, unsigned long val) +{ + return type_is_signed(type) && get_signed_val(type, val) < 0; +} + +static u_max get_unsigned_val(struct type_descriptor *type, unsigned long val) +{ + if (is_inline_int(type)) + return val; + + if (type_bit_width(type) == 64) + return *(u64 *)val; + + return *(u_max *)val; +} + +static void val_to_string(char *str, size_t size, struct type_descriptor *type, + unsigned long value) +{ + if (type_is_int(type)) { + if (type_bit_width(type) == 128) { +#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__) + u_max val = get_unsigned_val(type, value); + + scnprintf(str, size, "0x%08x%08x%08x%08x", + (u32)(val >> 96), + (u32)(val >> 64), + (u32)(val >> 32), + (u32)(val)); +#else + WARN_ON(1); +#endif + } else if (type_is_signed(type)) { + scnprintf(str, size, "%lld", + (s64)get_signed_val(type, value)); + } else { + scnprintf(str, size, "%llu", + (u64)get_unsigned_val(type, value)); + } + } +} + +static bool location_is_valid(struct source_location *loc) +{ + return loc->file_name != NULL; +} + +static DEFINE_SPINLOCK(report_lock); + +static void ubsan_prologue(struct source_location *location, + unsigned long *flags) +{ + current->in_ubsan++; + spin_lock_irqsave(&report_lock, *flags); + + pr_err("========================================" + "========================================\n"); + print_source_location("UBSAN: Undefined behaviour in", location); +} + +static void ubsan_epilogue(unsigned long *flags) +{ + dump_stack(); + pr_err("========================================" + "========================================\n"); + spin_unlock_irqrestore(&report_lock, *flags); + current->in_ubsan--; +} + +static void handle_overflow(struct overflow_data *data, unsigned long lhs, + unsigned long rhs, char op) +{ + + struct type_descriptor *type = data->type; + unsigned long flags; + char lhs_val_str[VALUE_LENGTH]; + char rhs_val_str[VALUE_LENGTH]; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + val_to_string(lhs_val_str, sizeof(lhs_val_str), type, lhs); + val_to_string(rhs_val_str, sizeof(rhs_val_str), type, rhs); + pr_err("%s integer overflow:\n", + type_is_signed(type) ? "signed" : "unsigned"); + pr_err("%s %c %s cannot be represented in type %s\n", + lhs_val_str, + op, + rhs_val_str, + type->type_name); + + ubsan_epilogue(&flags); +} + +void __ubsan_handle_add_overflow(struct overflow_data *data, + unsigned long lhs, + unsigned long rhs) +{ + + handle_overflow(data, lhs, rhs, '+'); +} +EXPORT_SYMBOL(__ubsan_handle_add_overflow); + +void __ubsan_handle_sub_overflow(struct overflow_data *data, + unsigned long lhs, + unsigned long rhs) +{ + handle_overflow(data, lhs, rhs, '-'); +} +EXPORT_SYMBOL(__ubsan_handle_sub_overflow); + +void __ubsan_handle_mul_overflow(struct overflow_data *data, + unsigned long lhs, + unsigned long rhs) +{ + handle_overflow(data, lhs, rhs, '*'); +} +EXPORT_SYMBOL(__ubsan_handle_mul_overflow); + +void __ubsan_handle_negate_overflow(struct overflow_data *data, + unsigned long old_val) +{ + unsigned long flags; + char old_val_str[VALUE_LENGTH]; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + val_to_string(old_val_str, sizeof(old_val_str), data->type, old_val); + + pr_err("negation of %s cannot be represented in type %s:\n", + old_val_str, data->type->type_name); + + ubsan_epilogue(&flags); +} +EXPORT_SYMBOL(__ubsan_handle_negate_overflow); + + +void __ubsan_handle_divrem_overflow(struct overflow_data *data, + unsigned long lhs, + unsigned long rhs) +{ + unsigned long flags; + char rhs_val_str[VALUE_LENGTH]; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + val_to_string(rhs_val_str, sizeof(rhs_val_str), data->type, rhs); + + if (type_is_signed(data->type) && get_signed_val(data->type, rhs) == -1) + pr_err("division of %s by -1 cannot be represented in type %s\n", + rhs_val_str, data->type->type_name); + else + pr_err("division by zero\n"); + + ubsan_epilogue(&flags); +} +EXPORT_SYMBOL(__ubsan_handle_divrem_overflow); + +static void handle_null_ptr_deref(struct type_mismatch_data *data) +{ + unsigned long flags; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + pr_err("%s null pointer of type %s\n", + type_check_kinds[data->type_check_kind], + data->type->type_name); + + ubsan_epilogue(&flags); +} + +static void handle_missaligned_access(struct type_mismatch_data *data, + unsigned long ptr) +{ + unsigned long flags; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + pr_err("%s misaligned address %p for type %s\n", + type_check_kinds[data->type_check_kind], + (void *)ptr, data->type->type_name); + pr_err("which requires %ld byte alignment\n", data->alignment); + + ubsan_epilogue(&flags); +} + +static void handle_object_size_mismatch(struct type_mismatch_data *data, + unsigned long ptr) +{ + unsigned long flags; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + pr_err("%s address %pk with insufficient space\n", + type_check_kinds[data->type_check_kind], + (void *) ptr); + pr_err("for an object of type %s\n", data->type->type_name); + ubsan_epilogue(&flags); +} + +void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, + unsigned long ptr) +{ + + if (!ptr) + handle_null_ptr_deref(data); + else if (data->alignment && !IS_ALIGNED(ptr, data->alignment)) + handle_missaligned_access(data, ptr); + else + handle_object_size_mismatch(data, ptr); +} +EXPORT_SYMBOL(__ubsan_handle_type_mismatch); + +void __ubsan_handle_nonnull_return(struct nonnull_return_data *data) +{ + unsigned long flags; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + pr_err("null pointer returned from function declared to never return null\n"); + + if (location_is_valid(&data->attr_location)) + print_source_location("returns_nonnull attribute specified in", + &data->attr_location); + + ubsan_epilogue(&flags); +} +EXPORT_SYMBOL(__ubsan_handle_nonnull_return); + +void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, + unsigned long bound) +{ + unsigned long flags; + char bound_str[VALUE_LENGTH]; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + val_to_string(bound_str, sizeof(bound_str), data->type, bound); + pr_err("variable length array bound value %s <= 0\n", bound_str); + + ubsan_epilogue(&flags); +} +EXPORT_SYMBOL(__ubsan_handle_vla_bound_not_positive); + +void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, + unsigned long index) +{ + unsigned long flags; + char index_str[VALUE_LENGTH]; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + val_to_string(index_str, sizeof(index_str), data->index_type, index); + pr_err("index %s is out of range for type %s\n", index_str, + data->array_type->type_name); + ubsan_epilogue(&flags); +} +EXPORT_SYMBOL(__ubsan_handle_out_of_bounds); + +void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, + unsigned long lhs, unsigned long rhs) +{ + unsigned long flags; + struct type_descriptor *rhs_type = data->rhs_type; + struct type_descriptor *lhs_type = data->lhs_type; + char rhs_str[VALUE_LENGTH]; + char lhs_str[VALUE_LENGTH]; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + val_to_string(rhs_str, sizeof(rhs_str), rhs_type, rhs); + val_to_string(lhs_str, sizeof(lhs_str), lhs_type, lhs); + + if (val_is_negative(rhs_type, rhs)) + pr_err("shift exponent %s is negative\n", rhs_str); + + else if (get_unsigned_val(rhs_type, rhs) >= + type_bit_width(lhs_type)) + pr_err("shift exponent %s is too large for %u-bit type %s\n", + rhs_str, + type_bit_width(lhs_type), + lhs_type->type_name); + else if (val_is_negative(lhs_type, lhs)) + pr_err("left shift of negative value %s\n", + lhs_str); + else + pr_err("left shift of %s by %s places cannot be" + " represented in type %s\n", + lhs_str, rhs_str, + lhs_type->type_name); + + ubsan_epilogue(&flags); +} +EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds); + + +void __noreturn +__ubsan_handle_builtin_unreachable(struct unreachable_data *data) +{ + unsigned long flags; + + ubsan_prologue(&data->location, &flags); + pr_err("calling __builtin_unreachable()\n"); + ubsan_epilogue(&flags); + panic("can't return from __builtin_unreachable()"); +} +EXPORT_SYMBOL(__ubsan_handle_builtin_unreachable); + +void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, + unsigned long val) +{ + unsigned long flags; + char val_str[VALUE_LENGTH]; + + if (suppress_report(&data->location)) + return; + + ubsan_prologue(&data->location, &flags); + + val_to_string(val_str, sizeof(val_str), data->type, val); + + pr_err("load of value %s is not a valid value for type %s\n", + val_str, data->type->type_name); + + ubsan_epilogue(&flags); +} +EXPORT_SYMBOL(__ubsan_handle_load_invalid_value); diff --git a/lib/ubsan.h b/lib/ubsan.h new file mode 100644 index 000000000000..b2d18d4a53f5 --- /dev/null +++ b/lib/ubsan.h @@ -0,0 +1,84 @@ +#ifndef _LIB_UBSAN_H +#define _LIB_UBSAN_H + +enum { + type_kind_int = 0, + type_kind_float = 1, + type_unknown = 0xffff +}; + +struct type_descriptor { + u16 type_kind; + u16 type_info; + char type_name[1]; +}; + +struct source_location { + const char *file_name; + union { + unsigned long reported; + struct { + u32 line; + u32 column; + }; + }; +}; + +struct overflow_data { + struct source_location location; + struct type_descriptor *type; +}; + +struct type_mismatch_data { + struct source_location location; + struct type_descriptor *type; + unsigned long alignment; + unsigned char type_check_kind; +}; + +struct nonnull_arg_data { + struct source_location location; + struct source_location attr_location; + int arg_index; +}; + +struct nonnull_return_data { + struct source_location location; + struct source_location attr_location; +}; + +struct vla_bound_data { + struct source_location location; + struct type_descriptor *type; +}; + +struct out_of_bounds_data { + struct source_location location; + struct type_descriptor *array_type; + struct type_descriptor *index_type; +}; + +struct shift_out_of_bounds_data { + struct source_location location; + struct type_descriptor *lhs_type; + struct type_descriptor *rhs_type; +}; + +struct unreachable_data { + struct source_location location; +}; + +struct invalid_value_data { + struct source_location location; + struct type_descriptor *type; +}; + +#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__) +typedef __int128 s_max; +typedef unsigned __int128 u_max; +#else +typedef s64 s_max; +typedef u64 u_max; +#endif + +#endif diff --git a/mm/kasan/Makefile b/mm/kasan/Makefile index 64710148941e..a61460d9f5b0 100644 --- a/mm/kasan/Makefile +++ b/mm/kasan/Makefile @@ -1,4 +1,5 @@ KASAN_SANITIZE := n +UBSAN_SANITIZE_kasan.o := n CFLAGS_REMOVE_kasan.o = -pg # Function splitter causes unnecessary splits in __asan_load1/__asan_store1 diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 39d6bb18ce76..2edbcadb3d7f 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -130,6 +130,12 @@ _c_flags += $(if $(patsubst n%,, \ $(CFLAGS_KASAN)) endif +ifeq ($(CONFIG_UBSAN),y) +_c_flags += $(if $(patsubst n%,, \ + $(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SANITIZE)$(CONFIG_UBSAN_SANITIZE_ALL)), \ + $(CFLAGS_UBSAN)) +endif + # If building the kernel in a separate objtree expand all occurrences # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/'). diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan new file mode 100644 index 000000000000..8ab68679cfb5 --- /dev/null +++ b/scripts/Makefile.ubsan @@ -0,0 +1,17 @@ +ifdef CONFIG_UBSAN + CFLAGS_UBSAN += $(call cc-option, -fsanitize=shift) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=integer-divide-by-zero) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=unreachable) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=vla-bound) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=null) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=signed-integer-overflow) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=object-size) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=returns-nonnull-attribute) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=bool) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=enum) + +ifdef CONFIG_UBSAN_ALIGNMENT + CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment) +endif +endif -- cgit v1.2.3 From c153693d7eb9eeb28478aa2deaaf0b4e7b5ff5e9 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 15 Jan 2016 20:52:22 +1100 Subject: powerpc: Simplify module TOC handling PowerPC64 uses the symbol .TOC. much as other targets use _GLOBAL_OFFSET_TABLE_. It identifies the value of the GOT pointer (or in powerpc parlance, the TOC pointer). Global offset tables are generally local to an executable or shared library, or in the kernel, module. Thus it does not make sense for a module to resolve a relocation against .TOC. to the kernel's .TOC. value. A module has its own .TOC., and indeed the powerpc64 module relocation processing ignores the kernel value of .TOC. and instead calculates a module-local value. This patch removes code involved in exporting the kernel .TOC., tweaks modpost to ignore an undefined .TOC., and the module loader to twiddle the section symbol so that .TOC. isn't seen as undefined. Note that if the kernel was compiled with -msingle-pic-base then ELFv2 would not have function global entry code setting up r2. In that case the module call stubs would need to be modified to set up r2 using the kernel .TOC. value, requiring some of this code to be reinstated. mpe: Furthermore a change in binutils master (not yet released) causes the current way we handle the TOC to no longer work when building with MODVERSIONS=y and RELOCATABLE=n. The symptom is that modules can not be loaded due to there being no version found for TOC. Cc: stable@vger.kernel.org # 3.16+ Signed-off-by: Alan Modra Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/misc_64.S | 28 ---------------------------- arch/powerpc/kernel/module_64.c | 12 +++++++++--- scripts/mod/modpost.c | 3 ++- 3 files changed, 11 insertions(+), 32 deletions(-) (limited to 'scripts') diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index db475d41b57a..f28754c497e5 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -701,31 +701,3 @@ _GLOBAL(kexec_sequence) li r5,0 blr /* image->start(physid, image->start, 0); */ #endif /* CONFIG_KEXEC */ - -#ifdef CONFIG_MODULES -#if defined(_CALL_ELF) && _CALL_ELF == 2 - -#ifdef CONFIG_MODVERSIONS -.weak __crc_TOC. -.section "___kcrctab+TOC.","a" -.globl __kcrctab_TOC. -__kcrctab_TOC.: - .llong __crc_TOC. -#endif - -/* - * Export a fake .TOC. since both modpost and depmod will complain otherwise. - * Both modpost and depmod strip the leading . so we do the same here. - */ -.section "__ksymtab_strings","a" -__kstrtab_TOC.: - .asciz "TOC." - -.section "___ksymtab+TOC.","a" -/* This symbol name is important: it's used by modpost to find exported syms */ -.globl __ksymtab_TOC. -__ksymtab_TOC.: - .llong 0 /* .value */ - .llong __kstrtab_TOC. -#endif /* ELFv2 */ -#endif /* MODULES */ diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 59663af9315f..ac64ffdb52c8 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -326,7 +326,10 @@ static void dedotify_versions(struct modversion_info *vers, } } -/* Undefined symbols which refer to .funcname, hack to funcname (or .TOC.) */ +/* + * Undefined symbols which refer to .funcname, hack to funcname. Make .TOC. + * seem to be defined (value set later). + */ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab) { unsigned int i; @@ -334,8 +337,11 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab) for (i = 1; i < numsyms; i++) { if (syms[i].st_shndx == SHN_UNDEF) { char *name = strtab + syms[i].st_name; - if (name[0] == '.') + if (name[0] == '.') { + if (strcmp(name+1, "TOC.") == 0) + syms[i].st_shndx = SHN_ABS; memmove(name, name+1, strlen(name)); + } } } } @@ -351,7 +357,7 @@ static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs, numsyms = sechdrs[symindex].sh_size / sizeof(Elf64_Sym); for (i = 1; i < numsyms; i++) { - if (syms[i].st_shndx == SHN_UNDEF + if (syms[i].st_shndx == SHN_ABS && strcmp(strtab + syms[i].st_name, "TOC.") == 0) return &syms[i]; } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index e080746e1a6b..48958d3cec9e 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -594,7 +594,8 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname) if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 || strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0 || strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 || - strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0) + strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0 || + strcmp(symname, ".TOC.") == 0) return 1; /* Do not ignore this symbol */ return 0; -- cgit v1.2.3