aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.build124
-rw-r--r--scripts/Makefile.extrawarn1
-rw-r--r--scripts/Makefile.gcc-plugins9
-rw-r--r--scripts/Makefile.modpost14
-rw-r--r--scripts/Makefile.ubsan9
-rw-r--r--scripts/basic/fixdep.c86
-rwxr-xr-xscripts/bloat-o-meter3
-rwxr-xr-xscripts/checkkconfigsymbols.py338
-rwxr-xr-xscripts/checkpatch.pl338
-rwxr-xr-xscripts/coccicheck2
-rw-r--r--scripts/coccinelle/api/memdup_user.cocci8
-rw-r--r--scripts/coccinelle/api/pm_runtime.cocci18
-rw-r--r--scripts/coccinelle/misc/cond_no_effect.cocci64
-rw-r--r--scripts/const_structs.checkpatch64
-rw-r--r--scripts/gcc-plugins/cyc_complexity_plugin.c4
-rw-r--r--scripts/gcc-plugins/gcc-common.h1
-rw-r--r--scripts/gcc-plugins/latent_entropy_plugin.c639
-rw-r--r--scripts/gcc-plugins/sancov_plugin.c4
-rwxr-xr-xscripts/gcc-x86_64-has-stack-protector.sh2
-rwxr-xr-xscripts/gen_initramfs_list.sh5
-rw-r--r--scripts/genksyms/lex.l35
-rw-r--r--scripts/genksyms/lex.lex.c_shipped35
-rwxr-xr-xscripts/kernel-doc48
-rwxr-xr-xscripts/link-vmlinux.sh71
-rw-r--r--scripts/mod/modpost.c2
-rw-r--r--scripts/recordmcount.c2
-rwxr-xr-xscripts/recordmcount.pl2
-rw-r--r--scripts/spelling.txt1
-rwxr-xr-xscripts/tags.sh3
-rwxr-xr-xscripts/tracing/ftrace-bisect.sh115
-rwxr-xr-xscripts/ver_linux260
31 files changed, 1709 insertions, 598 deletions
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 11602e5efb3b..7675d11ee65e 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -81,6 +81,7 @@ endif
81 81
82ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),) 82ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
83lib-target := $(obj)/lib.a 83lib-target := $(obj)/lib.a
84obj-y += $(obj)/lib-ksyms.o
84endif 85endif
85 86
86ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),) 87ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
@@ -158,7 +159,8 @@ cmd_cpp_i_c = $(CPP) $(c_flags) -o $@ $<
158$(obj)/%.i: $(src)/%.c FORCE 159$(obj)/%.i: $(src)/%.c FORCE
159 $(call if_changed_dep,cpp_i_c) 160 $(call if_changed_dep,cpp_i_c)
160 161
161cmd_gensymtypes = \ 162# These mirror gensymtypes_S and co below, keep them in synch.
163cmd_gensymtypes_c = \
162 $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ 164 $(CPP) -D__GENKSYMS__ $(c_flags) $< | \
163 $(GENKSYMS) $(if $(1), -T $(2)) \ 165 $(GENKSYMS) $(if $(1), -T $(2)) \
164 $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \ 166 $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \
@@ -168,7 +170,7 @@ cmd_gensymtypes = \
168quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ 170quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
169cmd_cc_symtypes_c = \ 171cmd_cc_symtypes_c = \
170 set -e; \ 172 set -e; \
171 $(call cmd_gensymtypes,true,$@) >/dev/null; \ 173 $(call cmd_gensymtypes_c,true,$@) >/dev/null; \
172 test -s $@ || rm -f $@ 174 test -s $@ || rm -f $@
173 175
174$(obj)/%.symtypes : $(src)/%.c FORCE 176$(obj)/%.symtypes : $(src)/%.c FORCE
@@ -197,9 +199,10 @@ else
197# the actual value of the checksum generated by genksyms 199# the actual value of the checksum generated by genksyms
198 200
199cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< 201cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
200cmd_modversions = \ 202
203cmd_modversions_c = \
201 if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ 204 if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
202 $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ 205 $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
203 > $(@D)/.tmp_$(@F:.o=.ver); \ 206 > $(@D)/.tmp_$(@F:.o=.ver); \
204 \ 207 \
205 $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ 208 $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
@@ -267,13 +270,14 @@ endif # CONFIG_STACK_VALIDATION
267define rule_cc_o_c 270define rule_cc_o_c
268 $(call echo-cmd,checksrc) $(cmd_checksrc) \ 271 $(call echo-cmd,checksrc) $(cmd_checksrc) \
269 $(call cmd_and_fixdep,cc_o_c) \ 272 $(call cmd_and_fixdep,cc_o_c) \
270 $(cmd_modversions) \ 273 $(cmd_modversions_c) \
271 $(cmd_objtool) \ 274 $(cmd_objtool) \
272 $(call echo-cmd,record_mcount) $(cmd_record_mcount) 275 $(call echo-cmd,record_mcount) $(cmd_record_mcount)
273endef 276endef
274 277
275define rule_as_o_S 278define rule_as_o_S
276 $(call cmd_and_fixdep,as_o_S) \ 279 $(call cmd_and_fixdep,as_o_S) \
280 $(cmd_modversions_S) \
277 $(cmd_objtool) 281 $(cmd_objtool)
278endef 282endef
279 283
@@ -313,6 +317,39 @@ modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL)
313$(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) 317$(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
314$(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) 318$(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE)
315 319
320# .S file exports must have their C prototypes defined in asm/asm-prototypes.h
321# or a file that it includes, in order to get versioned symbols. We build a
322# dummy C file that includes asm-prototypes and the EXPORT_SYMBOL lines from
323# the .S file (with trailing ';'), and run genksyms on that, to extract vers.
324#
325# This is convoluted. The .S file must first be preprocessed to run guards and
326# expand names, then the resulting exports must be constructed into plain
327# EXPORT_SYMBOL(symbol); to build our dummy C file, and that gets preprocessed
328# to make the genksyms input.
329#
330# These mirror gensymtypes_c and co above, keep them in synch.
331cmd_gensymtypes_S = \
332 (echo "\#include <linux/kernel.h>" ; \
333 echo "\#include <asm/asm-prototypes.h>" ; \
334 $(CPP) $(a_flags) $< | \
335 grep "\<___EXPORT_SYMBOL\>" | \
336 sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ) | \
337 $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \
338 $(GENKSYMS) $(if $(1), -T $(2)) \
339 $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \
340 $(if $(KBUILD_PRESERVE),-p) \
341 -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
342
343quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@
344cmd_cc_symtypes_S = \
345 set -e; \
346 $(call cmd_gensymtypes_S,true,$@) >/dev/null; \
347 test -s $@ || rm -f $@
348
349$(obj)/%.symtypes : $(src)/%.S FORCE
350 $(call cmd,cc_symtypes_S)
351
352
316quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@ 353quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@
317cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $< 354cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $<
318 355
@@ -320,7 +357,37 @@ $(obj)/%.s: $(src)/%.S FORCE
320 $(call if_changed_dep,cpp_s_S) 357 $(call if_changed_dep,cpp_s_S)
321 358
322quiet_cmd_as_o_S = AS $(quiet_modtag) $@ 359quiet_cmd_as_o_S = AS $(quiet_modtag) $@
323cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< 360
361ifndef CONFIG_MODVERSIONS
362cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
363
364else
365
366ASM_PROTOTYPES := $(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/asm-prototypes.h)
367
368ifeq ($(ASM_PROTOTYPES),)
369cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
370
371else
372
373# versioning matches the C process described above, with difference that
374# we parse asm-prototypes.h C header to get function definitions.
375
376cmd_as_o_S = $(CC) $(a_flags) -c -o $(@D)/.tmp_$(@F) $<
377
378cmd_modversions_S = \
379 if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
380 $(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
381 > $(@D)/.tmp_$(@F:.o=.ver); \
382 \
383 $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
384 -T $(@D)/.tmp_$(@F:.o=.ver); \
385 rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
386 else \
387 mv -f $(@D)/.tmp_$(@F) $@; \
388 fi;
389endif
390endif
324 391
325$(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE 392$(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
326 $(call if_changed_rule,as_o_S) 393 $(call if_changed_rule,as_o_S)
@@ -358,12 +425,22 @@ $(sort $(subdir-obj-y)): $(subdir-ym) ;
358# Rule to compile a set of .o files into one .o file 425# Rule to compile a set of .o files into one .o file
359# 426#
360ifdef builtin-target 427ifdef builtin-target
361quiet_cmd_link_o_target = LD $@ 428
429ifdef CONFIG_THIN_ARCHIVES
430 cmd_make_builtin = rm -f $@; $(AR) rcST$(KBUILD_ARFLAGS)
431 cmd_make_empty_builtin = rm -f $@; $(AR) rcST$(KBUILD_ARFLAGS)
432 quiet_cmd_link_o_target = AR $@
433else
434 cmd_make_builtin = $(LD) $(ld_flags) -r -o
435 cmd_make_empty_builtin = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS)
436 quiet_cmd_link_o_target = LD $@
437endif
438
362# If the list of objects to link is empty, just create an empty built-in.o 439# If the list of objects to link is empty, just create an empty built-in.o
363cmd_link_o_target = $(if $(strip $(obj-y)),\ 440cmd_link_o_target = $(if $(strip $(obj-y)),\
364 $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \ 441 $(cmd_make_builtin) $@ $(filter $(obj-y), $^) \
365 $(cmd_secanalysis),\ 442 $(cmd_secanalysis),\
366 rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@) 443 $(cmd_make_empty_builtin) $@)
367 444
368$(builtin-target): $(obj-y) FORCE 445$(builtin-target): $(obj-y) FORCE
369 $(call if_changed,link_o_target) 446 $(call if_changed,link_o_target)
@@ -389,12 +466,39 @@ $(modorder-target): $(subdir-ym) FORCE
389# 466#
390ifdef lib-target 467ifdef lib-target
391quiet_cmd_link_l_target = AR $@ 468quiet_cmd_link_l_target = AR $@
392cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y) 469
470ifdef CONFIG_THIN_ARCHIVES
471 cmd_link_l_target = rm -f $@; $(AR) rcsT$(KBUILD_ARFLAGS) $@ $(lib-y)
472else
473 cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y)
474endif
393 475
394$(lib-target): $(lib-y) FORCE 476$(lib-target): $(lib-y) FORCE
395 $(call if_changed,link_l_target) 477 $(call if_changed,link_l_target)
396 478
397targets += $(lib-target) 479targets += $(lib-target)
480
481dummy-object = $(obj)/.lib_exports.o
482ksyms-lds = $(dot-target).lds
483ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
484ref_prefix = EXTERN(_
485else
486ref_prefix = EXTERN(
487endif
488
489quiet_cmd_export_list = EXPORTS $@
490cmd_export_list = $(OBJDUMP) -h $< | \
491 sed -ne '/___ksymtab/{s/.*+/$(ref_prefix)/;s/ .*/)/;p}' >$(ksyms-lds);\
492 rm -f $(dummy-object);\
493 $(AR) rcs$(KBUILD_ARFLAGS) $(dummy-object);\
494 $(LD) $(ld_flags) -r -o $@ -T $(ksyms-lds) $(dummy-object);\
495 rm $(dummy-object) $(ksyms-lds)
496
497$(obj)/lib-ksyms.o: $(lib-target) FORCE
498 $(call if_changed,export_list)
499
500targets += $(obj)/lib-ksyms.o
501
398endif 502endif
399 503
400# 504#
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index 53449a6ff6aa..7c321a603b07 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -36,6 +36,7 @@ warning-2 += -Wshadow
36warning-2 += $(call cc-option, -Wlogical-op) 36warning-2 += $(call cc-option, -Wlogical-op)
37warning-2 += $(call cc-option, -Wmissing-field-initializers) 37warning-2 += $(call cc-option, -Wmissing-field-initializers)
38warning-2 += $(call cc-option, -Wsign-compare) 38warning-2 += $(call cc-option, -Wsign-compare)
39warning-2 += $(call cc-option, -Wmaybe-uninitialized)
39 40
40warning-3 := -Wbad-function-cast 41warning-3 := -Wbad-function-cast
41warning-3 += -Wcast-qual 42warning-3 += -Wcast-qual
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 61f0e6db909b..060d2cb373db 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -6,6 +6,12 @@ ifdef CONFIG_GCC_PLUGINS
6 6
7 gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so 7 gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so
8 8
9 gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so
10 gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += -DLATENT_ENTROPY_PLUGIN
11 ifdef CONFIG_PAX_LATENT_ENTROPY
12 DISABLE_LATENT_ENTROPY_PLUGIN += -fplugin-arg-latent_entropy_plugin-disable
13 endif
14
9 ifdef CONFIG_GCC_PLUGIN_SANCOV 15 ifdef CONFIG_GCC_PLUGIN_SANCOV
10 ifeq ($(CFLAGS_KCOV),) 16 ifeq ($(CFLAGS_KCOV),)
11 # It is needed because of the gcc-plugin.sh and gcc version checks. 17 # It is needed because of the gcc-plugin.sh and gcc version checks.
@@ -21,7 +27,8 @@ ifdef CONFIG_GCC_PLUGINS
21 27
22 GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) 28 GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
23 29
24 export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR SANCOV_PLUGIN 30 export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR
31 export SANCOV_PLUGIN DISABLE_LATENT_ENTROPY_PLUGIN
25 32
26 ifneq ($(PLUGINCC),) 33 ifneq ($(PLUGINCC),)
27 # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication. 34 # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication.
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 1366a94b6c39..16923ba4b5b1 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -115,14 +115,18 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
115 115
116targets += $(modules:.ko=.mod.o) 116targets += $(modules:.ko=.mod.o)
117 117
118# Step 6), final link of the modules 118ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
119
120# Step 6), final link of the modules with optional arch pass after final link
119quiet_cmd_ld_ko_o = LD [M] $@ 121quiet_cmd_ld_ko_o = LD [M] $@
120 cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ 122 cmd_ld_ko_o = \
121 $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ 123 $(LD) -r $(LDFLAGS) \
122 -o $@ $(filter-out FORCE,$^) 124 $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
125 -o $@ $(filter-out FORCE,$^) ; \
126 $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
123 127
124$(modules): %.ko :%.o %.mod.o FORCE 128$(modules): %.ko :%.o %.mod.o FORCE
125 $(call if_changed,ld_ko_o) 129 +$(call if_changed,ld_ko_o)
126 130
127targets += $(modules) 131targets += $(modules)
128 132
diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan
index 8ab68679cfb5..3b1b13818d59 100644
--- a/scripts/Makefile.ubsan
+++ b/scripts/Makefile.ubsan
@@ -3,7 +3,6 @@ ifdef CONFIG_UBSAN
3 CFLAGS_UBSAN += $(call cc-option, -fsanitize=integer-divide-by-zero) 3 CFLAGS_UBSAN += $(call cc-option, -fsanitize=integer-divide-by-zero)
4 CFLAGS_UBSAN += $(call cc-option, -fsanitize=unreachable) 4 CFLAGS_UBSAN += $(call cc-option, -fsanitize=unreachable)
5 CFLAGS_UBSAN += $(call cc-option, -fsanitize=vla-bound) 5 CFLAGS_UBSAN += $(call cc-option, -fsanitize=vla-bound)
6 CFLAGS_UBSAN += $(call cc-option, -fsanitize=null)
7 CFLAGS_UBSAN += $(call cc-option, -fsanitize=signed-integer-overflow) 6 CFLAGS_UBSAN += $(call cc-option, -fsanitize=signed-integer-overflow)
8 CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds) 7 CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds)
9 CFLAGS_UBSAN += $(call cc-option, -fsanitize=object-size) 8 CFLAGS_UBSAN += $(call cc-option, -fsanitize=object-size)
@@ -14,4 +13,12 @@ ifdef CONFIG_UBSAN
14ifdef CONFIG_UBSAN_ALIGNMENT 13ifdef CONFIG_UBSAN_ALIGNMENT
15 CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment) 14 CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment)
16endif 15endif
16
17ifdef CONFIG_UBSAN_NULL
18 CFLAGS_UBSAN += $(call cc-option, -fsanitize=null)
19endif
20
21 # -fsanitize=* options makes GCC less smart than usual and
22 # increase number of 'maybe-uninitialized false-positives
23 CFLAGS_UBSAN += $(call cc-option, -Wno-maybe-uninitialized)
17endif 24endif
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 746ec1ece614..fff818b92acb 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -82,8 +82,7 @@
82 * to date before even starting the recursive build, so it's too late 82 * to date before even starting the recursive build, so it's too late
83 * at this point anyway. 83 * at this point anyway.
84 * 84 *
85 * The algorithm to grep for "CONFIG_..." is bit unusual, but should 85 * We don't even try to really parse the header files, but
86 * be fast ;-) We don't even try to really parse the header files, but
87 * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will 86 * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
88 * be picked up as well. It's not a problem with respect to 87 * be picked up as well. It's not a problem with respect to
89 * correctness, since that can only give too many dependencies, thus 88 * correctness, since that can only give too many dependencies, thus
@@ -115,11 +114,6 @@
115#include <ctype.h> 114#include <ctype.h>
116#include <arpa/inet.h> 115#include <arpa/inet.h>
117 116
118#define INT_CONF ntohl(0x434f4e46)
119#define INT_ONFI ntohl(0x4f4e4649)
120#define INT_NFIG ntohl(0x4e464947)
121#define INT_FIG_ ntohl(0x4649475f)
122
123int insert_extra_deps; 117int insert_extra_deps;
124char *target; 118char *target;
125char *depfile; 119char *depfile;
@@ -241,37 +235,22 @@ static void use_config(const char *m, int slen)
241 print_config(m, slen); 235 print_config(m, slen);
242} 236}
243 237
244static void parse_config_file(const char *map, size_t len) 238static void parse_config_file(const char *p)
245{ 239{
246 const int *end = (const int *) (map + len); 240 const char *q, *r;
247 /* start at +1, so that p can never be < map */ 241
248 const int *m = (const int *) map + 1; 242 while ((p = strstr(p, "CONFIG_"))) {
249 const char *p, *q;
250
251 for (; m < end; m++) {
252 if (*m == INT_CONF) { p = (char *) m ; goto conf; }
253 if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
254 if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
255 if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
256 continue;
257 conf:
258 if (p > map + len - 7)
259 continue;
260 if (memcmp(p, "CONFIG_", 7))
261 continue;
262 p += 7; 243 p += 7;
263 for (q = p; q < map + len; q++) { 244 q = p;
264 if (!(isalnum(*q) || *q == '_')) 245 while (*q && (isalnum(*q) || *q == '_'))
265 goto found; 246 q++;
266 } 247 if (memcmp(q - 7, "_MODULE", 7) == 0)
267 continue; 248 r = q - 7;
268 249 else
269 found: 250 r = q;
270 if (!memcmp(q - 7, "_MODULE", 7)) 251 if (r > p)
271 q -= 7; 252 use_config(p, r - p);
272 if (q - p < 0) 253 p = q;
273 continue;
274 use_config(p, q - p);
275 } 254 }
276} 255}
277 256
@@ -291,7 +270,7 @@ static void do_config_file(const char *filename)
291{ 270{
292 struct stat st; 271 struct stat st;
293 int fd; 272 int fd;
294 void *map; 273 char *map;
295 274
296 fd = open(filename, O_RDONLY); 275 fd = open(filename, O_RDONLY);
297 if (fd < 0) { 276 if (fd < 0) {
@@ -308,18 +287,23 @@ static void do_config_file(const char *filename)
308 close(fd); 287 close(fd);
309 return; 288 return;
310 } 289 }
311 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 290 map = malloc(st.st_size + 1);
312 if ((long) map == -1) { 291 if (!map) {
313 perror("fixdep: mmap"); 292 perror("fixdep: malloc");
314 close(fd); 293 close(fd);
315 return; 294 return;
316 } 295 }
296 if (read(fd, map, st.st_size) != st.st_size) {
297 perror("fixdep: read");
298 close(fd);
299 return;
300 }
301 map[st.st_size] = '\0';
302 close(fd);
317 303
318 parse_config_file(map, st.st_size); 304 parse_config_file(map);
319
320 munmap(map, st.st_size);
321 305
322 close(fd); 306 free(map);
323} 307}
324 308
325/* 309/*
@@ -446,22 +430,8 @@ static void print_deps(void)
446 close(fd); 430 close(fd);
447} 431}
448 432
449static void traps(void)
450{
451 static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
452 int *p = (int *)test;
453
454 if (*p != INT_CONF) {
455 fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianness? %#x\n",
456 *p);
457 exit(2);
458 }
459}
460
461int main(int argc, char *argv[]) 433int main(int argc, char *argv[])
462{ 434{
463 traps();
464
465 if (argc == 5 && !strcmp(argv[1], "-e")) { 435 if (argc == 5 && !strcmp(argv[1], "-e")) {
466 insert_extra_deps = 1; 436 insert_extra_deps = 1;
467 argv++; 437 argv++;
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index 19f5adfd877d..d9ff038c1b28 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -8,6 +8,9 @@
8# of the GNU General Public License, incorporated herein by reference. 8# of the GNU General Public License, incorporated herein by reference.
9 9
10import sys, os, re 10import sys, os, re
11from signal import signal, SIGPIPE, SIG_DFL
12
13signal(SIGPIPE, SIG_DFL)
11 14
12if len(sys.argv) != 3: 15if len(sys.argv) != 3:
13 sys.stderr.write("usage: %s file1 file2\n" % sys.argv[0]) 16 sys.stderr.write("usage: %s file1 file2\n" % sys.argv[0])
diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py
index df643f60bb41..a32e4da4c117 100755
--- a/scripts/checkkconfigsymbols.py
+++ b/scripts/checkkconfigsymbols.py
@@ -1,98 +1,99 @@
1#!/usr/bin/env python2 1#!/usr/bin/env python3
2 2
3"""Find Kconfig symbols that are referenced but not defined.""" 3"""Find Kconfig symbols that are referenced but not defined."""
4 4
5# (c) 2014-2015 Valentin Rothberg <valentinrothberg@gmail.com> 5# (c) 2014-2016 Valentin Rothberg <valentinrothberg@gmail.com>
6# (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de> 6# (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
7# 7#
8# Licensed under the terms of the GNU GPL License version 2 8# Licensed under the terms of the GNU GPL License version 2
9 9
10 10
11import argparse
11import difflib 12import difflib
12import os 13import os
13import re 14import re
14import signal 15import signal
16import subprocess
15import sys 17import sys
16from multiprocessing import Pool, cpu_count 18from multiprocessing import Pool, cpu_count
17from optparse import OptionParser
18from subprocess import Popen, PIPE, STDOUT
19 19
20 20
21# regex expressions 21# regex expressions
22OPERATORS = r"&|\(|\)|\||\!" 22OPERATORS = r"&|\(|\)|\||\!"
23FEATURE = r"(?:\w*[A-Z0-9]\w*){2,}" 23SYMBOL = r"(?:\w*[A-Z0-9]\w*){2,}"
24DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*" 24DEF = r"^\s*(?:menu){,1}config\s+(" + SYMBOL + r")\s*"
25EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+" 25EXPR = r"(?:" + OPERATORS + r"|\s|" + SYMBOL + r")+"
26DEFAULT = r"default\s+.*?(?:if\s.+){,1}" 26DEFAULT = r"default\s+.*?(?:if\s.+){,1}"
27STMT = r"^\s*(?:if|select|depends\s+on|(?:" + DEFAULT + r"))\s+" + EXPR 27STMT = r"^\s*(?:if|select|depends\s+on|(?:" + DEFAULT + r"))\s+" + EXPR
28SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")" 28SOURCE_SYMBOL = r"(?:\W|\b)+[D]{,1}CONFIG_(" + SYMBOL + r")"
29 29
30# regex objects 30# regex objects
31REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") 31REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$")
32REGEX_FEATURE = re.compile(r'(?!\B)' + FEATURE + r'(?!\B)') 32REGEX_SYMBOL = re.compile(r'(?!\B)' + SYMBOL + r'(?!\B)')
33REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE) 33REGEX_SOURCE_SYMBOL = re.compile(SOURCE_SYMBOL)
34REGEX_KCONFIG_DEF = re.compile(DEF) 34REGEX_KCONFIG_DEF = re.compile(DEF)
35REGEX_KCONFIG_EXPR = re.compile(EXPR) 35REGEX_KCONFIG_EXPR = re.compile(EXPR)
36REGEX_KCONFIG_STMT = re.compile(STMT) 36REGEX_KCONFIG_STMT = re.compile(STMT)
37REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") 37REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$")
38REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$") 38REGEX_FILTER_SYMBOLS = re.compile(r"[A-Za-z0-9]$")
39REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") 39REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+")
40REGEX_QUOTES = re.compile("(\"(.*?)\")") 40REGEX_QUOTES = re.compile("(\"(.*?)\")")
41 41
42 42
43def parse_options(): 43def parse_options():
44 """The user interface of this module.""" 44 """The user interface of this module."""
45 usage = "%prog [options]\n\n" \ 45 usage = "Run this tool to detect Kconfig symbols that are referenced but " \
46 "Run this tool to detect Kconfig symbols that are referenced but " \ 46 "not defined in Kconfig. If no option is specified, " \
47 "not defined in\nKconfig. The output of this tool has the " \ 47 "checkkconfigsymbols defaults to check your current tree. " \
48 "format \'Undefined symbol\\tFile list\'\n\n" \ 48 "Please note that specifying commits will 'git reset --hard\' " \
49 "If no option is specified, %prog will default to check your\n" \ 49 "your current tree! You may save uncommitted changes to avoid " \
50 "current tree. Please note that specifying commits will " \ 50 "losing data."
51 "\'git reset --hard\'\nyour current tree! You may save " \ 51
52 "uncommitted changes to avoid losing data." 52 parser = argparse.ArgumentParser(description=usage)
53 53
54 parser = OptionParser(usage=usage) 54 parser.add_argument('-c', '--commit', dest='commit', action='store',
55 55 default="",
56 parser.add_option('-c', '--commit', dest='commit', action='store', 56 help="check if the specified commit (hash) introduces "
57 default="", 57 "undefined Kconfig symbols")
58 help="Check if the specified commit (hash) introduces " 58
59 "undefined Kconfig symbols.") 59 parser.add_argument('-d', '--diff', dest='diff', action='store',
60 60 default="",
61 parser.add_option('-d', '--diff', dest='diff', action='store', 61 help="diff undefined symbols between two commits "
62 default="", 62 "(e.g., -d commmit1..commit2)")
63 help="Diff undefined symbols between two commits. The " 63
64 "input format bases on Git log's " 64 parser.add_argument('-f', '--find', dest='find', action='store_true',
65 "\'commmit1..commit2\'.") 65 default=False,
66 66 help="find and show commits that may cause symbols to be "
67 parser.add_option('-f', '--find', dest='find', action='store_true', 67 "missing (required to run with --diff)")
68 default=False, 68
69 help="Find and show commits that may cause symbols to be " 69 parser.add_argument('-i', '--ignore', dest='ignore', action='store',
70 "missing. Required to run with --diff.") 70 default="",
71 71 help="ignore files matching this Python regex "
72 parser.add_option('-i', '--ignore', dest='ignore', action='store', 72 "(e.g., -i '.*defconfig')")
73 default="", 73
74 help="Ignore files matching this pattern. Note that " 74 parser.add_argument('-s', '--sim', dest='sim', action='store', default="",
75 "the pattern needs to be a Python regex. To " 75 help="print a list of max. 10 string-similar symbols")
76 "ignore defconfigs, specify -i '.*defconfig'.") 76
77 77 parser.add_argument('--force', dest='force', action='store_true',
78 parser.add_option('-s', '--sim', dest='sim', action='store', default="", 78 default=False,
79 help="Print a list of maximum 10 string-similar symbols.") 79 help="reset current Git tree even when it's dirty")
80 80
81 parser.add_option('', '--force', dest='force', action='store_true', 81 parser.add_argument('--no-color', dest='color', action='store_false',
82 default=False, 82 default=True,
83 help="Reset current Git tree even when it's dirty.") 83 help="don't print colored output (default when not "
84 84 "outputting to a terminal)")
85 (opts, _) = parser.parse_args() 85
86 86 args = parser.parse_args()
87 if opts.commit and opts.diff: 87
88 if args.commit and args.diff:
88 sys.exit("Please specify only one option at once.") 89 sys.exit("Please specify only one option at once.")
89 90
90 if opts.diff and not re.match(r"^[\w\-\.]+\.\.[\w\-\.]+$", opts.diff): 91 if args.diff and not re.match(r"^[\w\-\.]+\.\.[\w\-\.]+$", args.diff):
91 sys.exit("Please specify valid input in the following format: " 92 sys.exit("Please specify valid input in the following format: "
92 "\'commit1..commit2\'") 93 "\'commit1..commit2\'")
93 94
94 if opts.commit or opts.diff: 95 if args.commit or args.diff:
95 if not opts.force and tree_is_dirty(): 96 if not args.force and tree_is_dirty():
96 sys.exit("The current Git tree is dirty (see 'git status'). " 97 sys.exit("The current Git tree is dirty (see 'git status'). "
97 "Running this script may\ndelete important data since it " 98 "Running this script may\ndelete important data since it "
98 "calls 'git reset --hard' for some performance\nreasons. " 99 "calls 'git reset --hard' for some performance\nreasons. "
@@ -100,138 +101,148 @@ def parse_options():
100 "'--force' if you\nwant to ignore this warning and " 101 "'--force' if you\nwant to ignore this warning and "
101 "continue.") 102 "continue.")
102 103
103 if opts.commit: 104 if args.commit:
104 opts.find = False 105 args.find = False
105 106
106 if opts.ignore: 107 if args.ignore:
107 try: 108 try:
108 re.match(opts.ignore, "this/is/just/a/test.c") 109 re.match(args.ignore, "this/is/just/a/test.c")
109 except: 110 except:
110 sys.exit("Please specify a valid Python regex.") 111 sys.exit("Please specify a valid Python regex.")
111 112
112 return opts 113 return args
113 114
114 115
115def main(): 116def main():
116 """Main function of this module.""" 117 """Main function of this module."""
117 opts = parse_options() 118 args = parse_options()
118 119
119 if opts.sim and not opts.commit and not opts.diff: 120 global COLOR
120 sims = find_sims(opts.sim, opts.ignore) 121 COLOR = args.color and sys.stdout.isatty()
122
123 if args.sim and not args.commit and not args.diff:
124 sims = find_sims(args.sim, args.ignore)
121 if sims: 125 if sims:
122 print "%s: %s" % (yel("Similar symbols"), ', '.join(sims)) 126 print("%s: %s" % (yel("Similar symbols"), ', '.join(sims)))
123 else: 127 else:
124 print "%s: no similar symbols found" % yel("Similar symbols") 128 print("%s: no similar symbols found" % yel("Similar symbols"))
125 sys.exit(0) 129 sys.exit(0)
126 130
127 # dictionary of (un)defined symbols 131 # dictionary of (un)defined symbols
128 defined = {} 132 defined = {}
129 undefined = {} 133 undefined = {}
130 134
131 if opts.commit or opts.diff: 135 if args.commit or args.diff:
132 head = get_head() 136 head = get_head()
133 137
134 # get commit range 138 # get commit range
135 commit_a = None 139 commit_a = None
136 commit_b = None 140 commit_b = None
137 if opts.commit: 141 if args.commit:
138 commit_a = opts.commit + "~" 142 commit_a = args.commit + "~"
139 commit_b = opts.commit 143 commit_b = args.commit
140 elif opts.diff: 144 elif args.diff:
141 split = opts.diff.split("..") 145 split = args.diff.split("..")
142 commit_a = split[0] 146 commit_a = split[0]
143 commit_b = split[1] 147 commit_b = split[1]
144 undefined_a = {} 148 undefined_a = {}
145 undefined_b = {} 149 undefined_b = {}
146 150
147 # get undefined items before the commit 151 # get undefined items before the commit
148 execute("git reset --hard %s" % commit_a) 152 reset(commit_a)
149 undefined_a, _ = check_symbols(opts.ignore) 153 undefined_a, _ = check_symbols(args.ignore)
150 154
151 # get undefined items for the commit 155 # get undefined items for the commit
152 execute("git reset --hard %s" % commit_b) 156 reset(commit_b)
153 undefined_b, defined = check_symbols(opts.ignore) 157 undefined_b, defined = check_symbols(args.ignore)
154 158
155 # report cases that are present for the commit but not before 159 # report cases that are present for the commit but not before
156 for feature in sorted(undefined_b): 160 for symbol in sorted(undefined_b):
157 # feature has not been undefined before 161 # symbol has not been undefined before
158 if not feature in undefined_a: 162 if symbol not in undefined_a:
159 files = sorted(undefined_b.get(feature)) 163 files = sorted(undefined_b.get(symbol))
160 undefined[feature] = files 164 undefined[symbol] = files
161 # check if there are new files that reference the undefined feature 165 # check if there are new files that reference the undefined symbol
162 else: 166 else:
163 files = sorted(undefined_b.get(feature) - 167 files = sorted(undefined_b.get(symbol) -
164 undefined_a.get(feature)) 168 undefined_a.get(symbol))
165 if files: 169 if files:
166 undefined[feature] = files 170 undefined[symbol] = files
167 171
168 # reset to head 172 # reset to head
169 execute("git reset --hard %s" % head) 173 reset(head)
170 174
171 # default to check the entire tree 175 # default to check the entire tree
172 else: 176 else:
173 undefined, defined = check_symbols(opts.ignore) 177 undefined, defined = check_symbols(args.ignore)
174 178
175 # now print the output 179 # now print the output
176 for feature in sorted(undefined): 180 for symbol in sorted(undefined):
177 print red(feature) 181 print(red(symbol))
178 182
179 files = sorted(undefined.get(feature)) 183 files = sorted(undefined.get(symbol))
180 print "%s: %s" % (yel("Referencing files"), ", ".join(files)) 184 print("%s: %s" % (yel("Referencing files"), ", ".join(files)))
181 185
182 sims = find_sims(feature, opts.ignore, defined) 186 sims = find_sims(symbol, args.ignore, defined)
183 sims_out = yel("Similar symbols") 187 sims_out = yel("Similar symbols")
184 if sims: 188 if sims:
185 print "%s: %s" % (sims_out, ', '.join(sims)) 189 print("%s: %s" % (sims_out, ', '.join(sims)))
186 else: 190 else:
187 print "%s: %s" % (sims_out, "no similar symbols found") 191 print("%s: %s" % (sims_out, "no similar symbols found"))
188 192
189 if opts.find: 193 if args.find:
190 print "%s:" % yel("Commits changing symbol") 194 print("%s:" % yel("Commits changing symbol"))
191 commits = find_commits(feature, opts.diff) 195 commits = find_commits(symbol, args.diff)
192 if commits: 196 if commits:
193 for commit in commits: 197 for commit in commits:
194 commit = commit.split(" ", 1) 198 commit = commit.split(" ", 1)
195 print "\t- %s (\"%s\")" % (yel(commit[0]), commit[1]) 199 print("\t- %s (\"%s\")" % (yel(commit[0]), commit[1]))
196 else: 200 else:
197 print "\t- no commit found" 201 print("\t- no commit found")
198 print # new line 202 print() # new line
203
204
205def reset(commit):
206 """Reset current git tree to %commit."""
207 execute(["git", "reset", "--hard", commit])
199 208
200 209
201def yel(string): 210def yel(string):
202 """ 211 """
203 Color %string yellow. 212 Color %string yellow.
204 """ 213 """
205 return "\033[33m%s\033[0m" % string 214 return "\033[33m%s\033[0m" % string if COLOR else string
206 215
207 216
208def red(string): 217def red(string):
209 """ 218 """
210 Color %string red. 219 Color %string red.
211 """ 220 """
212 return "\033[31m%s\033[0m" % string 221 return "\033[31m%s\033[0m" % string if COLOR else string
213 222
214 223
215def execute(cmd): 224def execute(cmd):
216 """Execute %cmd and return stdout. Exit in case of error.""" 225 """Execute %cmd and return stdout. Exit in case of error."""
217 pop = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True) 226 try:
218 (stdout, _) = pop.communicate() # wait until finished 227 stdout = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=False)
219 if pop.returncode != 0: 228 stdout = stdout.decode(errors='replace')
220 sys.exit(stdout) 229 except subprocess.CalledProcessError as fail:
230 exit(fail)
221 return stdout 231 return stdout
222 232
223 233
224def find_commits(symbol, diff): 234def find_commits(symbol, diff):
225 """Find commits changing %symbol in the given range of %diff.""" 235 """Find commits changing %symbol in the given range of %diff."""
226 commits = execute("git log --pretty=oneline --abbrev-commit -G %s %s" 236 commits = execute(["git", "log", "--pretty=oneline",
227 % (symbol, diff)) 237 "--abbrev-commit", "-G",
238 symbol, diff])
228 return [x for x in commits.split("\n") if x] 239 return [x for x in commits.split("\n") if x]
229 240
230 241
231def tree_is_dirty(): 242def tree_is_dirty():
232 """Return true if the current working tree is dirty (i.e., if any file has 243 """Return true if the current working tree is dirty (i.e., if any file has
233 been added, deleted, modified, renamed or copied but not committed).""" 244 been added, deleted, modified, renamed or copied but not committed)."""
234 stdout = execute("git status --porcelain") 245 stdout = execute(["git", "status", "--porcelain"])
235 for line in stdout: 246 for line in stdout:
236 if re.findall(r"[URMADC]{1}", line[:2]): 247 if re.findall(r"[URMADC]{1}", line[:2]):
237 return True 248 return True
@@ -240,13 +251,13 @@ def tree_is_dirty():
240 251
241def get_head(): 252def get_head():
242 """Return commit hash of current HEAD.""" 253 """Return commit hash of current HEAD."""
243 stdout = execute("git rev-parse HEAD") 254 stdout = execute(["git", "rev-parse", "HEAD"])
244 return stdout.strip('\n') 255 return stdout.strip('\n')
245 256
246 257
247def partition(lst, size): 258def partition(lst, size):
248 """Partition list @lst into eveni-sized lists of size @size.""" 259 """Partition list @lst into eveni-sized lists of size @size."""
249 return [lst[i::size] for i in xrange(size)] 260 return [lst[i::size] for i in range(size)]
250 261
251 262
252def init_worker(): 263def init_worker():
@@ -254,7 +265,7 @@ def init_worker():
254 signal.signal(signal.SIGINT, signal.SIG_IGN) 265 signal.signal(signal.SIGINT, signal.SIG_IGN)
255 266
256 267
257def find_sims(symbol, ignore, defined = []): 268def find_sims(symbol, ignore, defined=[]):
258 """Return a list of max. ten Kconfig symbols that are string-similar to 269 """Return a list of max. ten Kconfig symbols that are string-similar to
259 @symbol.""" 270 @symbol."""
260 if defined: 271 if defined:
@@ -279,7 +290,7 @@ def find_sims(symbol, ignore, defined = []):
279def get_files(): 290def get_files():
280 """Return a list of all files in the current git directory.""" 291 """Return a list of all files in the current git directory."""
281 # use 'git ls-files' to get the worklist 292 # use 'git ls-files' to get the worklist
282 stdout = execute("git ls-files") 293 stdout = execute(["git", "ls-files"])
283 if len(stdout) > 0 and stdout[-1] == "\n": 294 if len(stdout) > 0 and stdout[-1] == "\n":
284 stdout = stdout[:-1] 295 stdout = stdout[:-1]
285 296
@@ -311,8 +322,8 @@ def check_symbols_helper(pool, ignore):
311 check_symbols() in order to properly terminate running worker processes.""" 322 check_symbols() in order to properly terminate running worker processes."""
312 source_files = [] 323 source_files = []
313 kconfig_files = [] 324 kconfig_files = []
314 defined_features = [] 325 defined_symbols = []
315 referenced_features = dict() # {file: [features]} 326 referenced_symbols = dict() # {file: [symbols]}
316 327
317 for gitfile in get_files(): 328 for gitfile in get_files():
318 if REGEX_FILE_KCONFIG.match(gitfile): 329 if REGEX_FILE_KCONFIG.match(gitfile):
@@ -326,76 +337,75 @@ def check_symbols_helper(pool, ignore):
326 # parse source files 337 # parse source files
327 arglist = partition(source_files, cpu_count()) 338 arglist = partition(source_files, cpu_count())
328 for res in pool.map(parse_source_files, arglist): 339 for res in pool.map(parse_source_files, arglist):
329 referenced_features.update(res) 340 referenced_symbols.update(res)
330
331 341
332 # parse kconfig files 342 # parse kconfig files
333 arglist = [] 343 arglist = []
334 for part in partition(kconfig_files, cpu_count()): 344 for part in partition(kconfig_files, cpu_count()):
335 arglist.append((part, ignore)) 345 arglist.append((part, ignore))
336 for res in pool.map(parse_kconfig_files, arglist): 346 for res in pool.map(parse_kconfig_files, arglist):
337 defined_features.extend(res[0]) 347 defined_symbols.extend(res[0])
338 referenced_features.update(res[1]) 348 referenced_symbols.update(res[1])
339 defined_features = set(defined_features) 349 defined_symbols = set(defined_symbols)
340 350
341 # inverse mapping of referenced_features to dict(feature: [files]) 351 # inverse mapping of referenced_symbols to dict(symbol: [files])
342 inv_map = dict() 352 inv_map = dict()
343 for _file, features in referenced_features.iteritems(): 353 for _file, symbols in referenced_symbols.items():
344 for feature in features: 354 for symbol in symbols:
345 inv_map[feature] = inv_map.get(feature, set()) 355 inv_map[symbol] = inv_map.get(symbol, set())
346 inv_map[feature].add(_file) 356 inv_map[symbol].add(_file)
347 referenced_features = inv_map 357 referenced_symbols = inv_map
348 358
349 undefined = {} # {feature: [files]} 359 undefined = {} # {symbol: [files]}
350 for feature in sorted(referenced_features): 360 for symbol in sorted(referenced_symbols):
351 # filter some false positives 361 # filter some false positives
352 if feature == "FOO" or feature == "BAR" or \ 362 if symbol == "FOO" or symbol == "BAR" or \
353 feature == "FOO_BAR" or feature == "XXX": 363 symbol == "FOO_BAR" or symbol == "XXX":
354 continue 364 continue
355 if feature not in defined_features: 365 if symbol not in defined_symbols:
356 if feature.endswith("_MODULE"): 366 if symbol.endswith("_MODULE"):
357 # avoid false positives for kernel modules 367 # avoid false positives for kernel modules
358 if feature[:-len("_MODULE")] in defined_features: 368 if symbol[:-len("_MODULE")] in defined_symbols:
359 continue 369 continue
360 undefined[feature] = referenced_features.get(feature) 370 undefined[symbol] = referenced_symbols.get(symbol)
361 return undefined, defined_features 371 return undefined, defined_symbols
362 372
363 373
364def parse_source_files(source_files): 374def parse_source_files(source_files):
365 """Parse each source file in @source_files and return dictionary with source 375 """Parse each source file in @source_files and return dictionary with source
366 files as keys and lists of references Kconfig symbols as values.""" 376 files as keys and lists of references Kconfig symbols as values."""
367 referenced_features = dict() 377 referenced_symbols = dict()
368 for sfile in source_files: 378 for sfile in source_files:
369 referenced_features[sfile] = parse_source_file(sfile) 379 referenced_symbols[sfile] = parse_source_file(sfile)
370 return referenced_features 380 return referenced_symbols
371 381
372 382
373def parse_source_file(sfile): 383def parse_source_file(sfile):
374 """Parse @sfile and return a list of referenced Kconfig features.""" 384 """Parse @sfile and return a list of referenced Kconfig symbols."""
375 lines = [] 385 lines = []
376 references = [] 386 references = []
377 387
378 if not os.path.exists(sfile): 388 if not os.path.exists(sfile):
379 return references 389 return references
380 390
381 with open(sfile, "r") as stream: 391 with open(sfile, "r", encoding='utf-8', errors='replace') as stream:
382 lines = stream.readlines() 392 lines = stream.readlines()
383 393
384 for line in lines: 394 for line in lines:
385 if not "CONFIG_" in line: 395 if "CONFIG_" not in line:
386 continue 396 continue
387 features = REGEX_SOURCE_FEATURE.findall(line) 397 symbols = REGEX_SOURCE_SYMBOL.findall(line)
388 for feature in features: 398 for symbol in symbols:
389 if not REGEX_FILTER_FEATURES.search(feature): 399 if not REGEX_FILTER_SYMBOLS.search(symbol):
390 continue 400 continue
391 references.append(feature) 401 references.append(symbol)
392 402
393 return references 403 return references
394 404
395 405
396def get_features_in_line(line): 406def get_symbols_in_line(line):
397 """Return mentioned Kconfig features in @line.""" 407 """Return mentioned Kconfig symbols in @line."""
398 return REGEX_FEATURE.findall(line) 408 return REGEX_SYMBOL.findall(line)
399 409
400 410
401def parse_kconfig_files(args): 411def parse_kconfig_files(args):
@@ -404,21 +414,21 @@ def parse_kconfig_files(args):
404 pattern.""" 414 pattern."""
405 kconfig_files = args[0] 415 kconfig_files = args[0]
406 ignore = args[1] 416 ignore = args[1]
407 defined_features = [] 417 defined_symbols = []
408 referenced_features = dict() 418 referenced_symbols = dict()
409 419
410 for kfile in kconfig_files: 420 for kfile in kconfig_files:
411 defined, references = parse_kconfig_file(kfile) 421 defined, references = parse_kconfig_file(kfile)
412 defined_features.extend(defined) 422 defined_symbols.extend(defined)
413 if ignore and re.match(ignore, kfile): 423 if ignore and re.match(ignore, kfile):
414 # do not collect references for files that match the ignore pattern 424 # do not collect references for files that match the ignore pattern
415 continue 425 continue
416 referenced_features[kfile] = references 426 referenced_symbols[kfile] = references
417 return (defined_features, referenced_features) 427 return (defined_symbols, referenced_symbols)
418 428
419 429
420def parse_kconfig_file(kfile): 430def parse_kconfig_file(kfile):
421 """Parse @kfile and update feature definitions and references.""" 431 """Parse @kfile and update symbol definitions and references."""
422 lines = [] 432 lines = []
423 defined = [] 433 defined = []
424 references = [] 434 references = []
@@ -427,7 +437,7 @@ def parse_kconfig_file(kfile):
427 if not os.path.exists(kfile): 437 if not os.path.exists(kfile):
428 return defined, references 438 return defined, references
429 439
430 with open(kfile, "r") as stream: 440 with open(kfile, "r", encoding='utf-8', errors='replace') as stream:
431 lines = stream.readlines() 441 lines = stream.readlines()
432 442
433 for i in range(len(lines)): 443 for i in range(len(lines)):
@@ -436,8 +446,8 @@ def parse_kconfig_file(kfile):
436 line = line.split("#")[0] # ignore comments 446 line = line.split("#")[0] # ignore comments
437 447
438 if REGEX_KCONFIG_DEF.match(line): 448 if REGEX_KCONFIG_DEF.match(line):
439 feature_def = REGEX_KCONFIG_DEF.findall(line) 449 symbol_def = REGEX_KCONFIG_DEF.findall(line)
440 defined.append(feature_def[0]) 450 defined.append(symbol_def[0])
441 skip = False 451 skip = False
442 elif REGEX_KCONFIG_HELP.match(line): 452 elif REGEX_KCONFIG_HELP.match(line):
443 skip = True 453 skip = True
@@ -446,18 +456,18 @@ def parse_kconfig_file(kfile):
446 pass 456 pass
447 elif REGEX_KCONFIG_STMT.match(line): 457 elif REGEX_KCONFIG_STMT.match(line):
448 line = REGEX_QUOTES.sub("", line) 458 line = REGEX_QUOTES.sub("", line)
449 features = get_features_in_line(line) 459 symbols = get_symbols_in_line(line)
450 # multi-line statements 460 # multi-line statements
451 while line.endswith("\\"): 461 while line.endswith("\\"):
452 i += 1 462 i += 1
453 line = lines[i] 463 line = lines[i]
454 line = line.strip('\n') 464 line = line.strip('\n')
455 features.extend(get_features_in_line(line)) 465 symbols.extend(get_symbols_in_line(line))
456 for feature in set(features): 466 for symbol in set(symbols):
457 if REGEX_NUMERIC.match(feature): 467 if REGEX_NUMERIC.match(symbol):
458 # ignore numeric values 468 # ignore numeric values
459 continue 469 continue
460 references.append(feature) 470 references.append(symbol)
461 471
462 return defined, references 472 return defined, references
463 473
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 206a6b346a8d..a8368d1c4348 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -54,6 +54,7 @@ my $min_conf_desc_length = 4;
54my $spelling_file = "$D/spelling.txt"; 54my $spelling_file = "$D/spelling.txt";
55my $codespell = 0; 55my $codespell = 0;
56my $codespellfile = "/usr/share/codespell/dictionary.txt"; 56my $codespellfile = "/usr/share/codespell/dictionary.txt";
57my $conststructsfile = "$D/const_structs.checkpatch";
57my $color = 1; 58my $color = 1;
58my $allow_c99_comments = 1; 59my $allow_c99_comments = 1;
59 60
@@ -523,7 +524,11 @@ our @mode_permission_funcs = (
523 ["module_param_array_named", 5], 524 ["module_param_array_named", 5],
524 ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], 525 ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2],
525 ["proc_create(?:_data|)", 2], 526 ["proc_create(?:_data|)", 2],
526 ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2], 527 ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2],
528 ["IIO_DEV_ATTR_[A-Z_]+", 1],
529 ["SENSOR_(?:DEVICE_|)ATTR_2", 2],
530 ["SENSOR_TEMPLATE(?:_2|)", 3],
531 ["__ATTR", 2],
527); 532);
528 533
529#Create a search pattern for all these functions to speed up a loop below 534#Create a search pattern for all these functions to speed up a loop below
@@ -541,6 +546,32 @@ our $mode_perms_world_writable = qr{
541 0[0-7][0-7][2367] 546 0[0-7][0-7][2367]
542}x; 547}x;
543 548
549our %mode_permission_string_types = (
550 "S_IRWXU" => 0700,
551 "S_IRUSR" => 0400,
552 "S_IWUSR" => 0200,
553 "S_IXUSR" => 0100,
554 "S_IRWXG" => 0070,
555 "S_IRGRP" => 0040,
556 "S_IWGRP" => 0020,
557 "S_IXGRP" => 0010,
558 "S_IRWXO" => 0007,
559 "S_IROTH" => 0004,
560 "S_IWOTH" => 0002,
561 "S_IXOTH" => 0001,
562 "S_IRWXUGO" => 0777,
563 "S_IRUGO" => 0444,
564 "S_IWUGO" => 0222,
565 "S_IXUGO" => 0111,
566);
567
568#Create a search pattern for all these strings to speed up a loop below
569our $mode_perms_string_search = "";
570foreach my $entry (keys %mode_permission_string_types) {
571 $mode_perms_string_search .= '|' if ($mode_perms_string_search ne "");
572 $mode_perms_string_search .= $entry;
573}
574
544our $allowed_asm_includes = qr{(?x: 575our $allowed_asm_includes = qr{(?x:
545 irq| 576 irq|
546 memory| 577 memory|
@@ -598,6 +629,29 @@ if ($codespell) {
598 629
599$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; 630$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
600 631
632my $const_structs = "";
633if (open(my $conststructs, '<', $conststructsfile)) {
634 while (<$conststructs>) {
635 my $line = $_;
636
637 $line =~ s/\s*\n?$//g;
638 $line =~ s/^\s*//g;
639
640 next if ($line =~ m/^\s*#/);
641 next if ($line =~ m/^\s*$/);
642 if ($line =~ /\s/) {
643 print("$conststructsfile: '$line' invalid - ignored\n");
644 next;
645 }
646
647 $const_structs .= '|' if ($const_structs ne "");
648 $const_structs .= $line;
649 }
650 close($conststructsfile);
651} else {
652 warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
653}
654
601sub build_types { 655sub build_types {
602 my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; 656 my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)";
603 my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; 657 my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)";
@@ -704,6 +758,16 @@ sub seed_camelcase_file {
704 } 758 }
705} 759}
706 760
761sub is_maintained_obsolete {
762 my ($filename) = @_;
763
764 return 0 if (!(-e "$root/scripts/get_maintainer.pl"));
765
766 my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
767
768 return $status =~ /obsolete/i;
769}
770
707my $camelcase_seeded = 0; 771my $camelcase_seeded = 0;
708sub seed_camelcase_includes { 772sub seed_camelcase_includes {
709 return if ($camelcase_seeded); 773 return if ($camelcase_seeded);
@@ -2289,6 +2353,10 @@ sub process {
2289 } 2353 }
2290 2354
2291 if ($found_file) { 2355 if ($found_file) {
2356 if (is_maintained_obsolete($realfile)) {
2357 WARN("OBSOLETE",
2358 "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. No unnecessary modifications please.\n");
2359 }
2292 if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { 2360 if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) {
2293 $check = 1; 2361 $check = 1;
2294 } else { 2362 } else {
@@ -2939,6 +3007,30 @@ sub process {
2939 "Block comments use a trailing */ on a separate line\n" . $herecurr); 3007 "Block comments use a trailing */ on a separate line\n" . $herecurr);
2940 } 3008 }
2941 3009
3010# Block comment * alignment
3011 if ($prevline =~ /$;[ \t]*$/ && #ends in comment
3012 $line =~ /^\+[ \t]*$;/ && #leading comment
3013 $rawline =~ /^\+[ \t]*\*/ && #leading *
3014 (($prevrawline =~ /^\+.*?\/\*/ && #leading /*
3015 $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */
3016 $prevrawline =~ /^\+[ \t]*\*/)) { #leading *
3017 my $oldindent;
3018 $prevrawline =~ m@^\+([ \t]*/?)\*@;
3019 if (defined($1)) {
3020 $oldindent = expand_tabs($1);
3021 } else {
3022 $prevrawline =~ m@^\+(.*/?)\*@;
3023 $oldindent = expand_tabs($1);
3024 }
3025 $rawline =~ m@^\+([ \t]*)\*@;
3026 my $newindent = $1;
3027 $newindent = expand_tabs($newindent);
3028 if (length($oldindent) ne length($newindent)) {
3029 WARN("BLOCK_COMMENT_STYLE",
3030 "Block comments should align the * on each line\n" . $hereprev);
3031 }
3032 }
3033
2942# check for missing blank lines after struct/union declarations 3034# check for missing blank lines after struct/union declarations
2943# with exceptions for various attributes and macros 3035# with exceptions for various attributes and macros
2944 if ($prevline =~ /^[\+ ]};?\s*$/ && 3036 if ($prevline =~ /^[\+ ]};?\s*$/ &&
@@ -4665,7 +4757,17 @@ sub process {
4665 $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); 4757 $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
4666 $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); 4758 $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/);
4667 4759
4668 $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; 4760 $dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;
4761 my $define_args = $1;
4762 my $define_stmt = $dstat;
4763 my @def_args = ();
4764
4765 if (defined $define_args && $define_args ne "") {
4766 $define_args = substr($define_args, 1, length($define_args) - 2);
4767 $define_args =~ s/\s*//g;
4768 @def_args = split(",", $define_args);
4769 }
4770
4669 $dstat =~ s/$;//g; 4771 $dstat =~ s/$;//g;
4670 $dstat =~ s/\\\n.//g; 4772 $dstat =~ s/\\\n.//g;
4671 $dstat =~ s/^\s*//s; 4773 $dstat =~ s/^\s*//s;
@@ -4701,6 +4803,15 @@ sub process {
4701 ^\[ 4803 ^\[
4702 }x; 4804 }x;
4703 #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; 4805 #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
4806
4807 $ctx =~ s/\n*$//;
4808 my $herectx = $here . "\n";
4809 my $stmt_cnt = statement_rawlines($ctx);
4810
4811 for (my $n = 0; $n < $stmt_cnt; $n++) {
4812 $herectx .= raw_line($linenr, $n) . "\n";
4813 }
4814
4704 if ($dstat ne '' && 4815 if ($dstat ne '' &&
4705 $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), 4816 $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
4706 $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); 4817 $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
@@ -4716,13 +4827,6 @@ sub process {
4716 $dstat !~ /^\(\{/ && # ({... 4827 $dstat !~ /^\(\{/ && # ({...
4717 $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) 4828 $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
4718 { 4829 {
4719 $ctx =~ s/\n*$//;
4720 my $herectx = $here . "\n";
4721 my $cnt = statement_rawlines($ctx);
4722
4723 for (my $n = 0; $n < $cnt; $n++) {
4724 $herectx .= raw_line($linenr, $n) . "\n";
4725 }
4726 4830
4727 if ($dstat =~ /;/) { 4831 if ($dstat =~ /;/) {
4728 ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", 4832 ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
@@ -4731,6 +4835,46 @@ sub process {
4731 ERROR("COMPLEX_MACRO", 4835 ERROR("COMPLEX_MACRO",
4732 "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); 4836 "Macros with complex values should be enclosed in parentheses\n" . "$herectx");
4733 } 4837 }
4838
4839 }
4840
4841 # Make $define_stmt single line, comment-free, etc
4842 my @stmt_array = split('\n', $define_stmt);
4843 my $first = 1;
4844 $define_stmt = "";
4845 foreach my $l (@stmt_array) {
4846 $l =~ s/\\$//;
4847 if ($first) {
4848 $define_stmt = $l;
4849 $first = 0;
4850 } elsif ($l =~ /^[\+ ]/) {
4851 $define_stmt .= substr($l, 1);
4852 }
4853 }
4854 $define_stmt =~ s/$;//g;
4855 $define_stmt =~ s/\s+/ /g;
4856 $define_stmt = trim($define_stmt);
4857
4858# check if any macro arguments are reused (ignore '...' and 'type')
4859 foreach my $arg (@def_args) {
4860 next if ($arg =~ /\.\.\./);
4861 next if ($arg =~ /^type$/i);
4862 my $tmp = $define_stmt;
4863 $tmp =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
4864 $tmp =~ s/\#+\s*$arg\b//g;
4865 $tmp =~ s/\b$arg\s*\#\#//g;
4866 my $use_cnt = $tmp =~ s/\b$arg\b//g;
4867 if ($use_cnt > 1) {
4868 CHK("MACRO_ARG_REUSE",
4869 "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
4870 }
4871# check if any macro arguments may have other precedence issues
4872 if ($define_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&
4873 ((defined($1) && $1 ne ',') ||
4874 (defined($2) && $2 ne ','))) {
4875 CHK("MACRO_ARG_PRECEDENCE",
4876 "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
4877 }
4734 } 4878 }
4735 4879
4736# check for macros with flow control, but without ## concatenation 4880# check for macros with flow control, but without ## concatenation
@@ -5495,46 +5639,46 @@ sub process {
5495 } 5639 }
5496 5640
5497# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) 5641# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
5498 if ($^V && $^V ge 5.10.0 && 5642# if ($^V && $^V ge 5.10.0 &&
5499 defined $stat && 5643# defined $stat &&
5500 $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 5644# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
5501 if (WARN("PREFER_ETHER_ADDR_COPY", 5645# if (WARN("PREFER_ETHER_ADDR_COPY",
5502 "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && 5646# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&
5503 $fix) { 5647# $fix) {
5504 $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; 5648# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
5505 } 5649# }
5506 } 5650# }
5507 5651
5508# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) 5652# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
5509 if ($^V && $^V ge 5.10.0 && 5653# if ($^V && $^V ge 5.10.0 &&
5510 defined $stat && 5654# defined $stat &&
5511 $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 5655# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
5512 WARN("PREFER_ETHER_ADDR_EQUAL", 5656# WARN("PREFER_ETHER_ADDR_EQUAL",
5513 "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") 5657# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")
5514 } 5658# }
5515 5659
5516# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr 5660# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr
5517# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr 5661# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr
5518 if ($^V && $^V ge 5.10.0 && 5662# if ($^V && $^V ge 5.10.0 &&
5519 defined $stat && 5663# defined $stat &&
5520 $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 5664# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
5521 5665#
5522 my $ms_val = $7; 5666# my $ms_val = $7;
5523 5667#
5524 if ($ms_val =~ /^(?:0x|)0+$/i) { 5668# if ($ms_val =~ /^(?:0x|)0+$/i) {
5525 if (WARN("PREFER_ETH_ZERO_ADDR", 5669# if (WARN("PREFER_ETH_ZERO_ADDR",
5526 "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && 5670# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&
5527 $fix) { 5671# $fix) {
5528 $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; 5672# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;
5529 } 5673# }
5530 } elsif ($ms_val =~ /^(?:0xff|255)$/i) { 5674# } elsif ($ms_val =~ /^(?:0xff|255)$/i) {
5531 if (WARN("PREFER_ETH_BROADCAST_ADDR", 5675# if (WARN("PREFER_ETH_BROADCAST_ADDR",
5532 "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && 5676# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&
5533 $fix) { 5677# $fix) {
5534 $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; 5678# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;
5535 } 5679# }
5536 } 5680# }
5537 } 5681# }
5538 5682
5539# typecasts on min/max could be min_t/max_t 5683# typecasts on min/max could be min_t/max_t
5540 if ($^V && $^V ge 5.10.0 && 5684 if ($^V && $^V ge 5.10.0 &&
@@ -5654,6 +5798,19 @@ sub process {
5654 "externs should be avoided in .c files\n" . $herecurr); 5798 "externs should be avoided in .c files\n" . $herecurr);
5655 } 5799 }
5656 5800
5801 if ($realfile =~ /\.[ch]$/ && defined $stat &&
5802 $stat =~ /^.\s*(?:extern\s+)?$Type\s*$Ident\s*\(\s*([^{]+)\s*\)\s*;/s &&
5803 $1 ne "void") {
5804 my $args = trim($1);
5805 while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
5806 my $arg = trim($1);
5807 if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
5808 WARN("FUNCTION_ARGUMENTS",
5809 "function definition argument '$arg' should also have an identifier name\n" . $herecurr);
5810 }
5811 }
5812 }
5813
5657# checks for new __setup's 5814# checks for new __setup's
5658 if ($rawline =~ /\b__setup\("([^"]*)"/) { 5815 if ($rawline =~ /\b__setup\("([^"]*)"/) {
5659 my $name = $1; 5816 my $name = $1;
@@ -5853,46 +6010,6 @@ sub process {
5853 } 6010 }
5854 6011
5855# check for various structs that are normally const (ops, kgdb, device_tree) 6012# check for various structs that are normally const (ops, kgdb, device_tree)
5856 my $const_structs = qr{
5857 acpi_dock_ops|
5858 address_space_operations|
5859 backlight_ops|
5860 block_device_operations|
5861 dentry_operations|
5862 dev_pm_ops|
5863 dma_map_ops|
5864 extent_io_ops|
5865 file_lock_operations|
5866 file_operations|
5867 hv_ops|
5868 ide_dma_ops|
5869 intel_dvo_dev_ops|
5870 item_operations|
5871 iwl_ops|
5872 kgdb_arch|
5873 kgdb_io|
5874 kset_uevent_ops|
5875 lock_manager_operations|
5876 microcode_ops|
5877 mtrr_ops|
5878 neigh_ops|
5879 nlmsvc_binding|
5880 of_device_id|
5881 pci_raw_ops|
5882 pipe_buf_operations|
5883 platform_hibernation_ops|
5884 platform_suspend_ops|
5885 proto_ops|
5886 rpc_pipe_ops|
5887 seq_operations|
5888 snd_ac97_build_ops|
5889 soc_pcmcia_socket_ops|
5890 stacktrace_ops|
5891 sysfs_ops|
5892 tty_operations|
5893 uart_ops|
5894 usb_mon_operations|
5895 wd_ops}x;
5896 if ($line !~ /\bconst\b/ && 6013 if ($line !~ /\bconst\b/ &&
5897 $line =~ /\bstruct\s+($const_structs)\b/) { 6014 $line =~ /\bstruct\s+($const_structs)\b/) {
5898 WARN("CONST_STRUCT", 6015 WARN("CONST_STRUCT",
@@ -5979,34 +6096,69 @@ sub process {
5979# Mode permission misuses where it seems decimal should be octal 6096# Mode permission misuses where it seems decimal should be octal
5980# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop 6097# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
5981 if ($^V && $^V ge 5.10.0 && 6098 if ($^V && $^V ge 5.10.0 &&
6099 defined $stat &&
5982 $line =~ /$mode_perms_search/) { 6100 $line =~ /$mode_perms_search/) {
5983 foreach my $entry (@mode_permission_funcs) { 6101 foreach my $entry (@mode_permission_funcs) {
5984 my $func = $entry->[0]; 6102 my $func = $entry->[0];
5985 my $arg_pos = $entry->[1]; 6103 my $arg_pos = $entry->[1];
5986 6104
6105 my $lc = $stat =~ tr@\n@@;
6106 $lc = $lc + $linenr;
6107 my $stat_real = raw_line($linenr, 0);
6108 for (my $count = $linenr + 1; $count <= $lc; $count++) {
6109 $stat_real = $stat_real . "\n" . raw_line($count, 0);
6110 }
6111
5987 my $skip_args = ""; 6112 my $skip_args = "";
5988 if ($arg_pos > 1) { 6113 if ($arg_pos > 1) {
5989 $arg_pos--; 6114 $arg_pos--;
5990 $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; 6115 $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
5991 } 6116 }
5992 my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]"; 6117 my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]";
5993 if ($line =~ /$test/) { 6118 if ($stat =~ /$test/) {
5994 my $val = $1; 6119 my $val = $1;
5995 $val = $6 if ($skip_args ne ""); 6120 $val = $6 if ($skip_args ne "");
5996 6121 if (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
5997 if ($val !~ /^0$/ && 6122 ($val =~ /^$Octal$/ && length($val) ne 4)) {
5998 (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
5999 length($val) ne 4)) {
6000 ERROR("NON_OCTAL_PERMISSIONS", 6123 ERROR("NON_OCTAL_PERMISSIONS",
6001 "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr); 6124 "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
6002 } elsif ($val =~ /^$Octal$/ && (oct($val) & 02)) { 6125 }
6126 if ($val =~ /^$Octal$/ && (oct($val) & 02)) {
6003 ERROR("EXPORTED_WORLD_WRITABLE", 6127 ERROR("EXPORTED_WORLD_WRITABLE",
6004 "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); 6128 "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real);
6005 } 6129 }
6006 } 6130 }
6007 } 6131 }
6008 } 6132 }
6009 6133
6134# check for uses of S_<PERMS> that could be octal for readability
6135 if ($line =~ /\b$mode_perms_string_search\b/) {
6136 my $val = "";
6137 my $oval = "";
6138 my $to = 0;
6139 my $curpos = 0;
6140 my $lastpos = 0;
6141 while ($line =~ /\b(($mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
6142 $curpos = pos($line);
6143 my $match = $2;
6144 my $omatch = $1;
6145 last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
6146 $lastpos = $curpos;
6147 $to |= $mode_permission_string_types{$match};
6148 $val .= '\s*\|\s*' if ($val ne "");
6149 $val .= $match;
6150 $oval .= $omatch;
6151 }
6152 $oval =~ s/^\s*\|\s*//;
6153 $oval =~ s/\s*\|\s*$//;
6154 my $octal = sprintf("%04o", $to);
6155 if (WARN("SYMBOLIC_PERMS",
6156 "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) &&
6157 $fix) {
6158 $fixed[$fixlinenr] =~ s/$val/$octal/;
6159 }
6160 }
6161
6010# validate content of MODULE_LICENSE against list from include/linux/module.h 6162# validate content of MODULE_LICENSE against list from include/linux/module.h
6011 if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { 6163 if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) {
6012 my $extracted_string = get_quoted_string($line, $rawline); 6164 my $extracted_string = get_quoted_string($line, $rawline);
diff --git a/scripts/coccicheck b/scripts/coccicheck
index c92c1528a54d..ec487b8e7051 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -1,7 +1,7 @@
1#!/bin/bash 1#!/bin/bash
2# Linux kernel coccicheck 2# Linux kernel coccicheck
3# 3#
4# Read Documentation/coccinelle.txt 4# Read Documentation/dev-tools/coccinelle.rst
5# 5#
6# This script requires at least spatch 6# This script requires at least spatch
7# version 1.0.0-rc11. 7# version 1.0.0-rc11.
diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci
index c606231b0e46..2a5aea8e8487 100644
--- a/scripts/coccinelle/api/memdup_user.cocci
+++ b/scripts/coccinelle/api/memdup_user.cocci
@@ -15,11 +15,11 @@ virtual org
15virtual report 15virtual report
16 16
17@depends on patch@ 17@depends on patch@
18expression from,to,size,flag; 18expression from,to,size;
19identifier l1,l2; 19identifier l1,l2;
20@@ 20@@
21 21
22- to = \(kmalloc\|kzalloc\)(size,flag); 22- to = \(kmalloc\|kzalloc\)(size,GFP_KERNEL);
23+ to = memdup_user(from,size); 23+ to = memdup_user(from,size);
24 if ( 24 if (
25- to==NULL 25- to==NULL
@@ -37,12 +37,12 @@ identifier l1,l2;
37- } 37- }
38 38
39@r depends on !patch@ 39@r depends on !patch@
40expression from,to,size,flag; 40expression from,to,size;
41position p; 41position p;
42statement S1,S2; 42statement S1,S2;
43@@ 43@@
44 44
45* to = \(kmalloc@p\|kzalloc@p\)(size,flag); 45* to = \(kmalloc@p\|kzalloc@p\)(size,GFP_KERNEL);
46 if (to==NULL || ...) S1 46 if (to==NULL || ...) S1
47 if (copy_from_user(to, from, size) != 0) 47 if (copy_from_user(to, from, size) != 0)
48 S2 48 S2
diff --git a/scripts/coccinelle/api/pm_runtime.cocci b/scripts/coccinelle/api/pm_runtime.cocci
index 89b98a2f7a6f..d67ccf5f8227 100644
--- a/scripts/coccinelle/api/pm_runtime.cocci
+++ b/scripts/coccinelle/api/pm_runtime.cocci
@@ -17,9 +17,10 @@ virtual report
17 17
18@runtime_bad_err_handle exists@ 18@runtime_bad_err_handle exists@
19expression ret; 19expression ret;
20position p;
20@@ 21@@
21( 22(
22ret = \(pm_runtime_idle\| 23ret@p = \(pm_runtime_idle\|
23 pm_runtime_suspend\| 24 pm_runtime_suspend\|
24 pm_runtime_autosuspend\| 25 pm_runtime_autosuspend\|
25 pm_runtime_resume\| 26 pm_runtime_resume\|
@@ -47,12 +48,13 @@ IS_ERR_VALUE(ret)
47// For context mode 48// For context mode
48//---------------------------------------------------------- 49//----------------------------------------------------------
49 50
50@depends on runtime_bad_err_handle && context@ 51@depends on context@
51identifier pm_runtime_api; 52identifier pm_runtime_api;
52expression ret; 53expression ret;
54position runtime_bad_err_handle.p;
53@@ 55@@
54( 56(
55ret = pm_runtime_api(...); 57ret@p = pm_runtime_api(...);
56... 58...
57* IS_ERR_VALUE(ret) 59* IS_ERR_VALUE(ret)
58... 60...
@@ -62,12 +64,13 @@ ret = pm_runtime_api(...);
62// For patch mode 64// For patch mode
63//---------------------------------------------------------- 65//----------------------------------------------------------
64 66
65@depends on runtime_bad_err_handle && patch@ 67@depends on patch@
66identifier pm_runtime_api; 68identifier pm_runtime_api;
67expression ret; 69expression ret;
70position runtime_bad_err_handle.p;
68@@ 71@@
69( 72(
70ret = pm_runtime_api(...); 73ret@p = pm_runtime_api(...);
71... 74...
72- IS_ERR_VALUE(ret) 75- IS_ERR_VALUE(ret)
73+ ret < 0 76+ ret < 0
@@ -78,13 +81,14 @@ ret = pm_runtime_api(...);
78// For org and report mode 81// For org and report mode
79//---------------------------------------------------------- 82//----------------------------------------------------------
80 83
81@r depends on runtime_bad_err_handle && (org || report) exists@ 84@r depends on (org || report) exists@
82position p1, p2; 85position p1, p2;
83identifier pm_runtime_api; 86identifier pm_runtime_api;
84expression ret; 87expression ret;
88position runtime_bad_err_handle.p;
85@@ 89@@
86( 90(
87ret = pm_runtime_api@p1(...); 91ret@p = pm_runtime_api@p1(...);
88... 92...
89IS_ERR_VALUE@p2(ret) 93IS_ERR_VALUE@p2(ret)
90... 94...
diff --git a/scripts/coccinelle/misc/cond_no_effect.cocci b/scripts/coccinelle/misc/cond_no_effect.cocci
new file mode 100644
index 000000000000..8467dbd1c465
--- /dev/null
+++ b/scripts/coccinelle/misc/cond_no_effect.cocci
@@ -0,0 +1,64 @@
1///Find conditions where if and else branch are functionally
2// identical.
3//
4// There can be false positives in cases where the positional
5// information is used (as with lockdep) or where the identity
6// is a placeholder for not yet handled cases.
7// Unfortunately there also seems to be a tendency to use
8// the last if else/else as a "default behavior" - which some
9// might consider a legitimate coding pattern. From discussion
10// on kernelnewbies though it seems that this is not really an
11// accepted pattern and if at all it would need to be commented
12//
13// In the Linux kernel it does not seem to actually report
14// false positives except for those that were documented as
15// being intentional.
16// the two known cases are:
17// arch/sh/kernel/traps_64.c:read_opcode()
18// } else if ((pc & 1) == 0) {
19// /* SHcompact */
20// /* TODO : provide handling for this. We don't really support
21// user-mode SHcompact yet, and for a kernel fault, this would
22// have to come from a module built for SHcompact. */
23// return -EFAULT;
24// } else {
25// /* misaligned */
26// return -EFAULT;
27// }
28// fs/kernfs/file.c:kernfs_fop_open()
29// * Both paths of the branch look the same. They're supposed to
30// * look that way and give @of->mutex different static lockdep keys.
31// */
32// if (has_mmap)
33// mutex_init(&of->mutex);
34// else
35// mutex_init(&of->mutex);
36//
37// All other cases look like bugs or at least lack of documentation
38//
39// Confidence: Moderate
40// Copyright: (C) 2016 Nicholas Mc Guire, OSADL. GPLv2.
41// Comments:
42// Options: --no-includes --include-headers
43
44virtual org
45virtual report
46
47@cond@
48statement S1;
49position p;
50@@
51
52* if@p (...) S1 else S1
53
54@script:python depends on org@
55p << cond.p;
56@@
57
58cocci.print_main("WARNING: possible condition with no effect (if == else)",p)
59
60@script:python depends on report@
61p << cond.p;
62@@
63
64coccilib.report.print_report(p[0],"WARNING: possible condition with no effect (if == else)")
diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch
new file mode 100644
index 000000000000..ac5f1267151d
--- /dev/null
+++ b/scripts/const_structs.checkpatch
@@ -0,0 +1,64 @@
1acpi_dock_ops
2address_space_operations
3backlight_ops
4block_device_operations
5clk_ops
6comedi_lrange
7component_ops
8dentry_operations
9dev_pm_ops
10dma_map_ops
11driver_info
12drm_connector_funcs
13drm_encoder_funcs
14drm_encoder_helper_funcs
15ethtool_ops
16extent_io_ops
17file_lock_operations
18file_operations
19hv_ops
20ide_dma_ops
21ide_port_ops
22inode_operations
23intel_dvo_dev_ops
24irq_domain_ops
25item_operations
26iwl_cfg
27iwl_ops
28kgdb_arch
29kgdb_io
30kset_uevent_ops
31lock_manager_operations
32machine_desc
33microcode_ops
34mlxsw_reg_info
35mtrr_ops
36neigh_ops
37net_device_ops
38nlmsvc_binding
39nvkm_device_chip
40of_device_id
41pci_raw_ops
42pipe_buf_operations
43platform_hibernation_ops
44platform_suspend_ops
45proto_ops
46regmap_access_table
47rpc_pipe_ops
48rtc_class_ops
49sd_desc
50seq_operations
51sirfsoc_padmux
52snd_ac97_build_ops
53snd_soc_component_driver
54soc_pcmcia_socket_ops
55stacktrace_ops
56sysfs_ops
57tty_operations
58uart_ops
59usb_mon_operations
60v4l2_ctrl_ops
61v4l2_ioctl_ops
62vm_operations_struct
63wacom_features
64wd_ops
diff --git a/scripts/gcc-plugins/cyc_complexity_plugin.c b/scripts/gcc-plugins/cyc_complexity_plugin.c
index 34df974c6ba3..8af7db06122d 100644
--- a/scripts/gcc-plugins/cyc_complexity_plugin.c
+++ b/scripts/gcc-plugins/cyc_complexity_plugin.c
@@ -20,7 +20,7 @@
20 20
21#include "gcc-common.h" 21#include "gcc-common.h"
22 22
23int plugin_is_GPL_compatible; 23__visible int plugin_is_GPL_compatible;
24 24
25static struct plugin_info cyc_complexity_plugin_info = { 25static struct plugin_info cyc_complexity_plugin_info = {
26 .version = "20160225", 26 .version = "20160225",
@@ -49,7 +49,7 @@ static unsigned int cyc_complexity_execute(void)
49 49
50#include "gcc-generate-gimple-pass.h" 50#include "gcc-generate-gimple-pass.h"
51 51
52int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) 52__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
53{ 53{
54 const char * const plugin_name = plugin_info->base_name; 54 const char * const plugin_name = plugin_info->base_name;
55 struct register_pass_info cyc_complexity_pass_info; 55 struct register_pass_info cyc_complexity_pass_info;
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 172850bcd0d9..950fd2e64bb7 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -130,6 +130,7 @@ extern void dump_gimple_stmt(pretty_printer *, gimple, int, int);
130#endif 130#endif
131 131
132#define __unused __attribute__((__unused__)) 132#define __unused __attribute__((__unused__))
133#define __visible __attribute__((visibility("default")))
133 134
134#define DECL_NAME_POINTER(node) IDENTIFIER_POINTER(DECL_NAME(node)) 135#define DECL_NAME_POINTER(node) IDENTIFIER_POINTER(DECL_NAME(node))
135#define DECL_NAME_LENGTH(node) IDENTIFIER_LENGTH(DECL_NAME(node)) 136#define DECL_NAME_LENGTH(node) IDENTIFIER_LENGTH(DECL_NAME(node))
diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c
new file mode 100644
index 000000000000..8160f1c1b56e
--- /dev/null
+++ b/scripts/gcc-plugins/latent_entropy_plugin.c
@@ -0,0 +1,639 @@
1/*
2 * Copyright 2012-2016 by the PaX Team <pageexec@freemail.hu>
3 * Copyright 2016 by Emese Revfy <re.emese@gmail.com>
4 * Licensed under the GPL v2
5 *
6 * Note: the choice of the license means that the compilation process is
7 * NOT 'eligible' as defined by gcc's library exception to the GPL v3,
8 * but for the kernel it doesn't matter since it doesn't link against
9 * any of the gcc libraries
10 *
11 * This gcc plugin helps generate a little bit of entropy from program state,
12 * used throughout the uptime of the kernel. Here is an instrumentation example:
13 *
14 * before:
15 * void __latent_entropy test(int argc, char *argv[])
16 * {
17 * if (argc <= 1)
18 * printf("%s: no command arguments :(\n", *argv);
19 * else
20 * printf("%s: %d command arguments!\n", *argv, args - 1);
21 * }
22 *
23 * after:
24 * void __latent_entropy test(int argc, char *argv[])
25 * {
26 * // latent_entropy_execute() 1.
27 * unsigned long local_entropy;
28 * // init_local_entropy() 1.
29 * void *local_entropy_frameaddr;
30 * // init_local_entropy() 3.
31 * unsigned long tmp_latent_entropy;
32 *
33 * // init_local_entropy() 2.
34 * local_entropy_frameaddr = __builtin_frame_address(0);
35 * local_entropy = (unsigned long) local_entropy_frameaddr;
36 *
37 * // init_local_entropy() 4.
38 * tmp_latent_entropy = latent_entropy;
39 * // init_local_entropy() 5.
40 * local_entropy ^= tmp_latent_entropy;
41 *
42 * // latent_entropy_execute() 3.
43 * if (argc <= 1) {
44 * // perturb_local_entropy()
45 * local_entropy += 4623067384293424948;
46 * printf("%s: no command arguments :(\n", *argv);
47 * // perturb_local_entropy()
48 * } else {
49 * local_entropy ^= 3896280633962944730;
50 * printf("%s: %d command arguments!\n", *argv, args - 1);
51 * }
52 *
53 * // latent_entropy_execute() 4.
54 * tmp_latent_entropy = rol(tmp_latent_entropy, local_entropy);
55 * latent_entropy = tmp_latent_entropy;
56 * }
57 *
58 * TODO:
59 * - add ipa pass to identify not explicitly marked candidate functions
60 * - mix in more program state (function arguments/return values,
61 * loop variables, etc)
62 * - more instrumentation control via attribute parameters
63 *
64 * BUGS:
65 * - none known
66 *
67 * Options:
68 * -fplugin-arg-latent_entropy_plugin-disable
69 *
70 * Attribute: __attribute__((latent_entropy))
71 * The latent_entropy gcc attribute can be only on functions and variables.
72 * If it is on a function then the plugin will instrument it. If the attribute
73 * is on a variable then the plugin will initialize it with a random value.
74 * The variable must be an integer, an integer array type or a structure
75 * with integer fields.
76 */
77
78#include "gcc-common.h"
79
80__visible int plugin_is_GPL_compatible;
81
82static GTY(()) tree latent_entropy_decl;
83
84static struct plugin_info latent_entropy_plugin_info = {
85 .version = "201606141920vanilla",
86 .help = "disable\tturn off latent entropy instrumentation\n",
87};
88
89static unsigned HOST_WIDE_INT seed;
90/*
91 * get_random_seed() (this is a GCC function) generates the seed.
92 * This is a simple random generator without any cryptographic security because
93 * the entropy doesn't come from here.
94 */
95static unsigned HOST_WIDE_INT get_random_const(void)
96{
97 unsigned int i;
98 unsigned HOST_WIDE_INT ret = 0;
99
100 for (i = 0; i < 8 * sizeof(ret); i++) {
101 ret = (ret << 1) | (seed & 1);
102 seed >>= 1;
103 if (ret & 1)
104 seed ^= 0xD800000000000000ULL;
105 }
106
107 return ret;
108}
109
110static tree tree_get_random_const(tree type)
111{
112 unsigned long long mask;
113
114 mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(type)) - 1);
115 mask = 2 * (mask - 1) + 1;
116
117 if (TYPE_UNSIGNED(type))
118 return build_int_cstu(type, mask & get_random_const());
119 return build_int_cst(type, mask & get_random_const());
120}
121
122static tree handle_latent_entropy_attribute(tree *node, tree name,
123 tree args __unused,
124 int flags __unused,
125 bool *no_add_attrs)
126{
127 tree type;
128#if BUILDING_GCC_VERSION <= 4007
129 VEC(constructor_elt, gc) *vals;
130#else
131 vec<constructor_elt, va_gc> *vals;
132#endif
133
134 switch (TREE_CODE(*node)) {
135 default:
136 *no_add_attrs = true;
137 error("%qE attribute only applies to functions and variables",
138 name);
139 break;
140
141 case VAR_DECL:
142 if (DECL_INITIAL(*node)) {
143 *no_add_attrs = true;
144 error("variable %qD with %qE attribute must not be initialized",
145 *node, name);
146 break;
147 }
148
149 if (!TREE_STATIC(*node)) {
150 *no_add_attrs = true;
151 error("variable %qD with %qE attribute must not be local",
152 *node, name);
153 break;
154 }
155
156 type = TREE_TYPE(*node);
157 switch (TREE_CODE(type)) {
158 default:
159 *no_add_attrs = true;
160 error("variable %qD with %qE attribute must be an integer or a fixed length integer array type or a fixed sized structure with integer fields",
161 *node, name);
162 break;
163
164 case RECORD_TYPE: {
165 tree fld, lst = TYPE_FIELDS(type);
166 unsigned int nelt = 0;
167
168 for (fld = lst; fld; nelt++, fld = TREE_CHAIN(fld)) {
169 tree fieldtype;
170
171 fieldtype = TREE_TYPE(fld);
172 if (TREE_CODE(fieldtype) == INTEGER_TYPE)
173 continue;
174
175 *no_add_attrs = true;
176 error("structure variable %qD with %qE attribute has a non-integer field %qE",
177 *node, name, fld);
178 break;
179 }
180
181 if (fld)
182 break;
183
184#if BUILDING_GCC_VERSION <= 4007
185 vals = VEC_alloc(constructor_elt, gc, nelt);
186#else
187 vec_alloc(vals, nelt);
188#endif
189
190 for (fld = lst; fld; fld = TREE_CHAIN(fld)) {
191 tree random_const, fld_t = TREE_TYPE(fld);
192
193 random_const = tree_get_random_const(fld_t);
194 CONSTRUCTOR_APPEND_ELT(vals, fld, random_const);
195 }
196
197 /* Initialize the fields with random constants */
198 DECL_INITIAL(*node) = build_constructor(type, vals);
199 break;
200 }
201
202 /* Initialize the variable with a random constant */
203 case INTEGER_TYPE:
204 DECL_INITIAL(*node) = tree_get_random_const(type);
205 break;
206
207 case ARRAY_TYPE: {
208 tree elt_type, array_size, elt_size;
209 unsigned int i, nelt;
210 HOST_WIDE_INT array_size_int, elt_size_int;
211
212 elt_type = TREE_TYPE(type);
213 elt_size = TYPE_SIZE_UNIT(TREE_TYPE(type));
214 array_size = TYPE_SIZE_UNIT(type);
215
216 if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size
217 || TREE_CODE(array_size) != INTEGER_CST) {
218 *no_add_attrs = true;
219 error("array variable %qD with %qE attribute must be a fixed length integer array type",
220 *node, name);
221 break;
222 }
223
224 array_size_int = TREE_INT_CST_LOW(array_size);
225 elt_size_int = TREE_INT_CST_LOW(elt_size);
226 nelt = array_size_int / elt_size_int;
227
228#if BUILDING_GCC_VERSION <= 4007
229 vals = VEC_alloc(constructor_elt, gc, nelt);
230#else
231 vec_alloc(vals, nelt);
232#endif
233
234 for (i = 0; i < nelt; i++) {
235 tree cst = size_int(i);
236 tree rand_cst = tree_get_random_const(elt_type);
237
238 CONSTRUCTOR_APPEND_ELT(vals, cst, rand_cst);
239 }
240
241 /*
242 * Initialize the elements of the array with random
243 * constants
244 */
245 DECL_INITIAL(*node) = build_constructor(type, vals);
246 break;
247 }
248 }
249 break;
250
251 case FUNCTION_DECL:
252 break;
253 }
254
255 return NULL_TREE;
256}
257
258static struct attribute_spec latent_entropy_attr = {
259 .name = "latent_entropy",
260 .min_length = 0,
261 .max_length = 0,
262 .decl_required = true,
263 .type_required = false,
264 .function_type_required = false,
265 .handler = handle_latent_entropy_attribute,
266#if BUILDING_GCC_VERSION >= 4007
267 .affects_type_identity = false
268#endif
269};
270
271static void register_attributes(void *event_data __unused, void *data __unused)
272{
273 register_attribute(&latent_entropy_attr);
274}
275
276static bool latent_entropy_gate(void)
277{
278 tree list;
279
280 /* don't bother with noreturn functions for now */
281 if (TREE_THIS_VOLATILE(current_function_decl))
282 return false;
283
284 /* gcc-4.5 doesn't discover some trivial noreturn functions */
285 if (EDGE_COUNT(EXIT_BLOCK_PTR_FOR_FN(cfun)->preds) == 0)
286 return false;
287
288 list = DECL_ATTRIBUTES(current_function_decl);
289 return lookup_attribute("latent_entropy", list) != NULL_TREE;
290}
291
292static tree create_var(tree type, const char *name)
293{
294 tree var;
295
296 var = create_tmp_var(type, name);
297 add_referenced_var(var);
298 mark_sym_for_renaming(var);
299 return var;
300}
301
302/*
303 * Set up the next operation and its constant operand to use in the latent
304 * entropy PRNG. When RHS is specified, the request is for perturbing the
305 * local latent entropy variable, otherwise it is for perturbing the global
306 * latent entropy variable where the two operands are already given by the
307 * local and global latent entropy variables themselves.
308 *
309 * The operation is one of add/xor/rol when instrumenting the local entropy
310 * variable and one of add/xor when perturbing the global entropy variable.
311 * Rotation is not used for the latter case because it would transmit less
312 * entropy to the global variable than the other two operations.
313 */
314static enum tree_code get_op(tree *rhs)
315{
316 static enum tree_code op;
317 unsigned HOST_WIDE_INT random_const;
318
319 random_const = get_random_const();
320
321 switch (op) {
322 case BIT_XOR_EXPR:
323 op = PLUS_EXPR;
324 break;
325
326 case PLUS_EXPR:
327 if (rhs) {
328 op = LROTATE_EXPR;
329 /*
330 * This code limits the value of random_const to
331 * the size of a wide int for the rotation
332 */
333 random_const &= HOST_BITS_PER_WIDE_INT - 1;
334 break;
335 }
336
337 case LROTATE_EXPR:
338 default:
339 op = BIT_XOR_EXPR;
340 break;
341 }
342 if (rhs)
343 *rhs = build_int_cstu(long_unsigned_type_node, random_const);
344 return op;
345}
346
347static gimple create_assign(enum tree_code code, tree lhs, tree op1,
348 tree op2)
349{
350 return gimple_build_assign_with_ops(code, lhs, op1, op2);
351}
352
353static void perturb_local_entropy(basic_block bb, tree local_entropy)
354{
355 gimple_stmt_iterator gsi;
356 gimple assign;
357 tree rhs;
358 enum tree_code op;
359
360 op = get_op(&rhs);
361 assign = create_assign(op, local_entropy, local_entropy, rhs);
362 gsi = gsi_after_labels(bb);
363 gsi_insert_before(&gsi, assign, GSI_NEW_STMT);
364 update_stmt(assign);
365}
366
367static void __perturb_latent_entropy(gimple_stmt_iterator *gsi,
368 tree local_entropy)
369{
370 gimple assign;
371 tree temp;
372 enum tree_code op;
373
374 /* 1. create temporary copy of latent_entropy */
375 temp = create_var(long_unsigned_type_node, "temp_latent_entropy");
376
377 /* 2. read... */
378 add_referenced_var(latent_entropy_decl);
379 mark_sym_for_renaming(latent_entropy_decl);
380 assign = gimple_build_assign(temp, latent_entropy_decl);
381 gsi_insert_before(gsi, assign, GSI_NEW_STMT);
382 update_stmt(assign);
383
384 /* 3. ...modify... */
385 op = get_op(NULL);
386 assign = create_assign(op, temp, temp, local_entropy);
387 gsi_insert_after(gsi, assign, GSI_NEW_STMT);
388 update_stmt(assign);
389
390 /* 4. ...write latent_entropy */
391 assign = gimple_build_assign(latent_entropy_decl, temp);
392 gsi_insert_after(gsi, assign, GSI_NEW_STMT);
393 update_stmt(assign);
394}
395
396static bool handle_tail_calls(basic_block bb, tree local_entropy)
397{
398 gimple_stmt_iterator gsi;
399
400 for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
401 gcall *call;
402 gimple stmt = gsi_stmt(gsi);
403
404 if (!is_gimple_call(stmt))
405 continue;
406
407 call = as_a_gcall(stmt);
408 if (!gimple_call_tail_p(call))
409 continue;
410
411 __perturb_latent_entropy(&gsi, local_entropy);
412 return true;
413 }
414
415 return false;
416}
417
418static void perturb_latent_entropy(tree local_entropy)
419{
420 edge_iterator ei;
421 edge e, last_bb_e;
422 basic_block last_bb;
423
424 gcc_assert(single_pred_p(EXIT_BLOCK_PTR_FOR_FN(cfun)));
425 last_bb_e = single_pred_edge(EXIT_BLOCK_PTR_FOR_FN(cfun));
426
427 FOR_EACH_EDGE(e, ei, last_bb_e->src->preds) {
428 if (ENTRY_BLOCK_PTR_FOR_FN(cfun) == e->src)
429 continue;
430 if (EXIT_BLOCK_PTR_FOR_FN(cfun) == e->src)
431 continue;
432
433 handle_tail_calls(e->src, local_entropy);
434 }
435
436 last_bb = single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun));
437 if (!handle_tail_calls(last_bb, local_entropy)) {
438 gimple_stmt_iterator gsi = gsi_last_bb(last_bb);
439
440 __perturb_latent_entropy(&gsi, local_entropy);
441 }
442}
443
444static void init_local_entropy(basic_block bb, tree local_entropy)
445{
446 gimple assign, call;
447 tree frame_addr, rand_const, tmp, fndecl, udi_frame_addr;
448 enum tree_code op;
449 unsigned HOST_WIDE_INT rand_cst;
450 gimple_stmt_iterator gsi = gsi_after_labels(bb);
451
452 /* 1. create local_entropy_frameaddr */
453 frame_addr = create_var(ptr_type_node, "local_entropy_frameaddr");
454
455 /* 2. local_entropy_frameaddr = __builtin_frame_address() */
456 fndecl = builtin_decl_implicit(BUILT_IN_FRAME_ADDRESS);
457 call = gimple_build_call(fndecl, 1, integer_zero_node);
458 gimple_call_set_lhs(call, frame_addr);
459 gsi_insert_before(&gsi, call, GSI_NEW_STMT);
460 update_stmt(call);
461
462 udi_frame_addr = fold_convert(long_unsigned_type_node, frame_addr);
463 assign = gimple_build_assign(local_entropy, udi_frame_addr);
464 gsi_insert_after(&gsi, assign, GSI_NEW_STMT);
465 update_stmt(assign);
466
467 /* 3. create temporary copy of latent_entropy */
468 tmp = create_var(long_unsigned_type_node, "temp_latent_entropy");
469
470 /* 4. read the global entropy variable into local entropy */
471 add_referenced_var(latent_entropy_decl);
472 mark_sym_for_renaming(latent_entropy_decl);
473 assign = gimple_build_assign(tmp, latent_entropy_decl);
474 gsi_insert_after(&gsi, assign, GSI_NEW_STMT);
475 update_stmt(assign);
476
477 /* 5. mix local_entropy_frameaddr into local entropy */
478 assign = create_assign(BIT_XOR_EXPR, local_entropy, local_entropy, tmp);
479 gsi_insert_after(&gsi, assign, GSI_NEW_STMT);
480 update_stmt(assign);
481
482 rand_cst = get_random_const();
483 rand_const = build_int_cstu(long_unsigned_type_node, rand_cst);
484 op = get_op(NULL);
485 assign = create_assign(op, local_entropy, local_entropy, rand_const);
486 gsi_insert_after(&gsi, assign, GSI_NEW_STMT);
487 update_stmt(assign);
488}
489
490static bool create_latent_entropy_decl(void)
491{
492 varpool_node_ptr node;
493
494 if (latent_entropy_decl != NULL_TREE)
495 return true;
496
497 FOR_EACH_VARIABLE(node) {
498 tree name, var = NODE_DECL(node);
499
500 if (DECL_NAME_LENGTH(var) < sizeof("latent_entropy") - 1)
501 continue;
502
503 name = DECL_NAME(var);
504 if (strcmp(IDENTIFIER_POINTER(name), "latent_entropy"))
505 continue;
506
507 latent_entropy_decl = var;
508 break;
509 }
510
511 return latent_entropy_decl != NULL_TREE;
512}
513
514static unsigned int latent_entropy_execute(void)
515{
516 basic_block bb;
517 tree local_entropy;
518
519 if (!create_latent_entropy_decl())
520 return 0;
521
522 /* prepare for step 2 below */
523 gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
524 bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
525 if (!single_pred_p(bb)) {
526 split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
527 gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
528 bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
529 }
530
531 /* 1. create the local entropy variable */
532 local_entropy = create_var(long_unsigned_type_node, "local_entropy");
533
534 /* 2. initialize the local entropy variable */
535 init_local_entropy(bb, local_entropy);
536
537 bb = bb->next_bb;
538
539 /*
540 * 3. instrument each BB with an operation on the
541 * local entropy variable
542 */
543 while (bb != EXIT_BLOCK_PTR_FOR_FN(cfun)) {
544 perturb_local_entropy(bb, local_entropy);
545 bb = bb->next_bb;
546 };
547
548 /* 4. mix local entropy into the global entropy variable */
549 perturb_latent_entropy(local_entropy);
550 return 0;
551}
552
553static void latent_entropy_start_unit(void *gcc_data __unused,
554 void *user_data __unused)
555{
556 tree type, id;
557 int quals;
558
559 seed = get_random_seed(false);
560
561 if (in_lto_p)
562 return;
563
564 /* extern volatile unsigned long latent_entropy */
565 quals = TYPE_QUALS(long_unsigned_type_node) | TYPE_QUAL_VOLATILE;
566 type = build_qualified_type(long_unsigned_type_node, quals);
567 id = get_identifier("latent_entropy");
568 latent_entropy_decl = build_decl(UNKNOWN_LOCATION, VAR_DECL, id, type);
569
570 TREE_STATIC(latent_entropy_decl) = 1;
571 TREE_PUBLIC(latent_entropy_decl) = 1;
572 TREE_USED(latent_entropy_decl) = 1;
573 DECL_PRESERVE_P(latent_entropy_decl) = 1;
574 TREE_THIS_VOLATILE(latent_entropy_decl) = 1;
575 DECL_EXTERNAL(latent_entropy_decl) = 1;
576 DECL_ARTIFICIAL(latent_entropy_decl) = 1;
577 lang_hooks.decls.pushdecl(latent_entropy_decl);
578}
579
580#define PASS_NAME latent_entropy
581#define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg
582#define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func \
583 | TODO_update_ssa
584#include "gcc-generate-gimple-pass.h"
585
586__visible int plugin_init(struct plugin_name_args *plugin_info,
587 struct plugin_gcc_version *version)
588{
589 bool enabled = true;
590 const char * const plugin_name = plugin_info->base_name;
591 const int argc = plugin_info->argc;
592 const struct plugin_argument * const argv = plugin_info->argv;
593 int i;
594
595 struct register_pass_info latent_entropy_pass_info;
596
597 latent_entropy_pass_info.pass = make_latent_entropy_pass();
598 latent_entropy_pass_info.reference_pass_name = "optimized";
599 latent_entropy_pass_info.ref_pass_instance_number = 1;
600 latent_entropy_pass_info.pos_op = PASS_POS_INSERT_BEFORE;
601 static const struct ggc_root_tab gt_ggc_r_gt_latent_entropy[] = {
602 {
603 .base = &latent_entropy_decl,
604 .nelt = 1,
605 .stride = sizeof(latent_entropy_decl),
606 .cb = &gt_ggc_mx_tree_node,
607 .pchw = &gt_pch_nx_tree_node
608 },
609 LAST_GGC_ROOT_TAB
610 };
611
612 if (!plugin_default_version_check(version, &gcc_version)) {
613 error(G_("incompatible gcc/plugin versions"));
614 return 1;
615 }
616
617 for (i = 0; i < argc; ++i) {
618 if (!(strcmp(argv[i].key, "disable"))) {
619 enabled = false;
620 continue;
621 }
622 error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
623 }
624
625 register_callback(plugin_name, PLUGIN_INFO, NULL,
626 &latent_entropy_plugin_info);
627 if (enabled) {
628 register_callback(plugin_name, PLUGIN_START_UNIT,
629 &latent_entropy_start_unit, NULL);
630 register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS,
631 NULL, (void *)&gt_ggc_r_gt_latent_entropy);
632 register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
633 &latent_entropy_pass_info);
634 }
635 register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes,
636 NULL);
637
638 return 0;
639}
diff --git a/scripts/gcc-plugins/sancov_plugin.c b/scripts/gcc-plugins/sancov_plugin.c
index aedd6113cb73..7ea0b3f50739 100644
--- a/scripts/gcc-plugins/sancov_plugin.c
+++ b/scripts/gcc-plugins/sancov_plugin.c
@@ -21,7 +21,7 @@
21 21
22#include "gcc-common.h" 22#include "gcc-common.h"
23 23
24int plugin_is_GPL_compatible; 24__visible int plugin_is_GPL_compatible;
25 25
26tree sancov_fndecl; 26tree sancov_fndecl;
27 27
@@ -86,7 +86,7 @@ static void sancov_start_unit(void __unused *gcc_data, void __unused *user_data)
86#endif 86#endif
87} 87}
88 88
89int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) 89__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
90{ 90{
91 int i; 91 int i;
92 struct register_pass_info sancov_plugin_pass_info; 92 struct register_pass_info sancov_plugin_pass_info;
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh
index 973e8c141567..17867e723a51 100755
--- a/scripts/gcc-x86_64-has-stack-protector.sh
+++ b/scripts/gcc-x86_64-has-stack-protector.sh
@@ -1,6 +1,6 @@
1#!/bin/sh 1#!/bin/sh
2 2
3echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" 3echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fno-PIE -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
4if [ "$?" -eq "0" ] ; then 4if [ "$?" -eq "0" ] ; then
5 echo y 5 echo y
6else 6else
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 17fa901418ae..0055b07b03b6 100755
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -97,7 +97,10 @@ print_mtime() {
97} 97}
98 98
99list_parse() { 99list_parse() {
100 [ ! -L "$1" ] && echo "$1 \\" || : 100 if [ -L "$1" ]; then
101 return
102 fi
103 echo "$1" | sed 's/:/\\:/g; s/$/ \\/'
101} 104}
102 105
103# for each file print a line in following format 106# for each file print a line in following format
diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l
index e583565f2011..5235aa507ba5 100644
--- a/scripts/genksyms/lex.l
+++ b/scripts/genksyms/lex.l
@@ -289,6 +289,23 @@ repeat:
289 } 289 }
290 break; 290 break;
291 291
292 case ST_TYPEOF_1:
293 if (token == IDENT)
294 {
295 if (is_reserved_word(yytext, yyleng)
296 || find_symbol(yytext, SYM_TYPEDEF, 1))
297 {
298 yyless(0);
299 unput('(');
300 lexstate = ST_NORMAL;
301 token = TYPEOF_KEYW;
302 break;
303 }
304 _APP("(", 1);
305 }
306 lexstate = ST_TYPEOF;
307 /* FALLTHRU */
308
292 case ST_TYPEOF: 309 case ST_TYPEOF:
293 switch (token) 310 switch (token)
294 { 311 {
@@ -313,24 +330,6 @@ repeat:
313 } 330 }
314 break; 331 break;
315 332
316 case ST_TYPEOF_1:
317 if (token == IDENT)
318 {
319 if (is_reserved_word(yytext, yyleng)
320 || find_symbol(yytext, SYM_TYPEDEF, 1))
321 {
322 yyless(0);
323 unput('(');
324 lexstate = ST_NORMAL;
325 token = TYPEOF_KEYW;
326 break;
327 }
328 _APP("(", 1);
329 }
330 APP;
331 lexstate = ST_TYPEOF;
332 goto repeat;
333
334 case ST_BRACKET: 333 case ST_BRACKET:
335 APP; 334 APP;
336 switch (token) 335 switch (token)
diff --git a/scripts/genksyms/lex.lex.c_shipped b/scripts/genksyms/lex.lex.c_shipped
index f82740a69b85..985c5541aae4 100644
--- a/scripts/genksyms/lex.lex.c_shipped
+++ b/scripts/genksyms/lex.lex.c_shipped
@@ -2098,6 +2098,23 @@ repeat:
2098 } 2098 }
2099 break; 2099 break;
2100 2100
2101 case ST_TYPEOF_1:
2102 if (token == IDENT)
2103 {
2104 if (is_reserved_word(yytext, yyleng)
2105 || find_symbol(yytext, SYM_TYPEDEF, 1))
2106 {
2107 yyless(0);
2108 unput('(');
2109 lexstate = ST_NORMAL;
2110 token = TYPEOF_KEYW;
2111 break;
2112 }
2113 _APP("(", 1);
2114 }
2115 lexstate = ST_TYPEOF;
2116 /* FALLTHRU */
2117
2101 case ST_TYPEOF: 2118 case ST_TYPEOF:
2102 switch (token) 2119 switch (token)
2103 { 2120 {
@@ -2122,24 +2139,6 @@ repeat:
2122 } 2139 }
2123 break; 2140 break;
2124 2141
2125 case ST_TYPEOF_1:
2126 if (token == IDENT)
2127 {
2128 if (is_reserved_word(yytext, yyleng)
2129 || find_symbol(yytext, SYM_TYPEDEF, 1))
2130 {
2131 yyless(0);
2132 unput('(');
2133 lexstate = ST_NORMAL;
2134 token = TYPEOF_KEYW;
2135 break;
2136 }
2137 _APP("(", 1);
2138 }
2139 APP;
2140 lexstate = ST_TYPEOF;
2141 goto repeat;
2142
2143 case ST_BRACKET: 2142 case ST_BRACKET:
2144 APP; 2143 APP;
2145 switch (token) 2144 switch (token)
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 4f2e9049e8fa..93721f3c91bf 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -212,6 +212,7 @@ my $anon_struct_union = 0;
212my $type_constant = '\%([-_\w]+)'; 212my $type_constant = '\%([-_\w]+)';
213my $type_func = '(\w+)\(\)'; 213my $type_func = '(\w+)\(\)';
214my $type_param = '\@(\w+)'; 214my $type_param = '\@(\w+)';
215my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params
215my $type_struct = '\&((struct\s*)*[_\w]+)'; 216my $type_struct = '\&((struct\s*)*[_\w]+)';
216my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)'; 217my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
217my $type_env = '(\$\w+)'; 218my $type_env = '(\$\w+)';
@@ -292,6 +293,7 @@ my @highlights_rst = (
292 # Note: need to escape () to avoid func matching later 293 # Note: need to escape () to avoid func matching later
293 [$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"], 294 [$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"],
294 [$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"], 295 [$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"],
296 [$type_fp_param, "**\$1\\\\(\\\\)**"],
295 [$type_func, "\\:c\\:func\\:`\$1()`"], 297 [$type_func, "\\:c\\:func\\:`\$1()`"],
296 [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], 298 [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
297 [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], 299 [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
@@ -412,7 +414,7 @@ my $doc_com_body = '\s*\* ?';
412my $doc_decl = $doc_com . '(\w+)'; 414my $doc_decl = $doc_com . '(\w+)';
413# @params and a strictly limited set of supported section names 415# @params and a strictly limited set of supported section names
414my $doc_sect = $doc_com . 416my $doc_sect = $doc_com .
415 '\s*(\@\w+|description|context|returns?|notes?|examples?)\s*:(.*)'; 417 '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)';
416my $doc_content = $doc_com_body . '(.*)'; 418my $doc_content = $doc_com_body . '(.*)';
417my $doc_block = $doc_com . 'DOC:\s*(.*)?'; 419my $doc_block = $doc_com . 'DOC:\s*(.*)?';
418my $doc_inline_start = '^\s*/\*\*\s*$'; 420my $doc_inline_start = '^\s*/\*\*\s*$';
@@ -1831,13 +1833,22 @@ sub output_function_rst(%) {
1831 my %args = %{$_[0]}; 1833 my %args = %{$_[0]};
1832 my ($parameter, $section); 1834 my ($parameter, $section);
1833 my $oldprefix = $lineprefix; 1835 my $oldprefix = $lineprefix;
1834 my $start; 1836 my $start = "";
1835 1837
1836 print ".. c:function:: "; 1838 if ($args{'typedef'}) {
1839 print ".. c:type:: ". $args{'function'} . "\n\n";
1840 print_lineno($declaration_start_line);
1841 print " **Typedef**: ";
1842 $lineprefix = "";
1843 output_highlight_rst($args{'purpose'});
1844 $start = "\n\n**Syntax**\n\n ``";
1845 } else {
1846 print ".. c:function:: ";
1847 }
1837 if ($args{'functiontype'} ne "") { 1848 if ($args{'functiontype'} ne "") {
1838 $start = $args{'functiontype'} . " " . $args{'function'} . " ("; 1849 $start .= $args{'functiontype'} . " " . $args{'function'} . " (";
1839 } else { 1850 } else {
1840 $start = $args{'function'} . " ("; 1851 $start .= $args{'function'} . " (";
1841 } 1852 }
1842 print $start; 1853 print $start;
1843 1854
@@ -1849,9 +1860,6 @@ sub output_function_rst(%) {
1849 $count++; 1860 $count++;
1850 $type = $args{'parametertypes'}{$parameter}; 1861 $type = $args{'parametertypes'}{$parameter};
1851 1862
1852 # RST doesn't like address_space tags at function prototypes
1853 $type =~ s/__(user|kernel|iomem|percpu|pmem|rcu)\s*//;
1854
1855 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1863 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1856 # pointer-to-function 1864 # pointer-to-function
1857 print $1 . $parameter . ") (" . $2; 1865 print $1 . $parameter . ") (" . $2;
@@ -1859,11 +1867,15 @@ sub output_function_rst(%) {
1859 print $type . " " . $parameter; 1867 print $type . " " . $parameter;
1860 } 1868 }
1861 } 1869 }
1862 print ")\n\n"; 1870 if ($args{'typedef'}) {
1863 print_lineno($declaration_start_line); 1871 print ");``\n\n";
1864 $lineprefix = " "; 1872 } else {
1865 output_highlight_rst($args{'purpose'}); 1873 print ")\n\n";
1866 print "\n"; 1874 print_lineno($declaration_start_line);
1875 $lineprefix = " ";
1876 output_highlight_rst($args{'purpose'});
1877 print "\n";
1878 }
1867 1879
1868 print "**Parameters**\n\n"; 1880 print "**Parameters**\n\n";
1869 $lineprefix = " "; 1881 $lineprefix = " ";
@@ -2003,7 +2015,7 @@ sub output_struct_rst(%) {
2003 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 2015 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
2004 $type = $args{'parametertypes'}{$parameter}; 2016 $type = $args{'parametertypes'}{$parameter};
2005 print_lineno($parameterdesc_start_lines{$parameter_name}); 2017 print_lineno($parameterdesc_start_lines{$parameter_name});
2006 print "``$type $parameter``\n"; 2018 print "``" . $parameter . "``\n";
2007 output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 2019 output_highlight_rst($args{'parameterdescs'}{$parameter_name});
2008 print "\n"; 2020 print "\n";
2009 } 2021 }
@@ -2193,7 +2205,9 @@ sub dump_typedef($$) {
2193 $x =~ s@/\*.*?\*/@@gos; # strip comments. 2205 $x =~ s@/\*.*?\*/@@gos; # strip comments.
2194 2206
2195 # Parse function prototypes 2207 # Parse function prototypes
2196 if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/) { 2208 if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
2209 $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
2210
2197 # Function typedefs 2211 # Function typedefs
2198 $return_type = $1; 2212 $return_type = $1;
2199 $declaration_name = $2; 2213 $declaration_name = $2;
@@ -2204,6 +2218,7 @@ sub dump_typedef($$) {
2204 output_declaration($declaration_name, 2218 output_declaration($declaration_name,
2205 'function', 2219 'function',
2206 {'function' => $declaration_name, 2220 {'function' => $declaration_name,
2221 'typedef' => 1,
2207 'module' => $modulename, 2222 'module' => $modulename,
2208 'functiontype' => $return_type, 2223 'functiontype' => $return_type,
2209 'parameterlist' => \@parameterlist, 2224 'parameterlist' => \@parameterlist,
@@ -2338,6 +2353,7 @@ sub push_parameter($$$) {
2338 2353
2339 if ($type eq "" && $param =~ /\.\.\.$/) 2354 if ($type eq "" && $param =~ /\.\.\.$/)
2340 { 2355 {
2356 $param = "...";
2341 if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { 2357 if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
2342 $parameterdescs{$param} = "variable arguments"; 2358 $parameterdescs{$param} = "variable arguments";
2343 } 2359 }
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 4f727eb5ec43..f742c65108b9 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -37,12 +37,40 @@ info()
37 fi 37 fi
38} 38}
39 39
40# Thin archive build here makes a final archive with
41# symbol table and indexes from vmlinux objects, which can be
42# used as input to linker.
43#
44# Traditional incremental style of link does not require this step
45#
46# built-in.o output file
47#
48archive_builtin()
49{
50 if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
51 info AR built-in.o
52 rm -f built-in.o;
53 ${AR} rcsT${KBUILD_ARFLAGS} built-in.o \
54 ${KBUILD_VMLINUX_INIT} \
55 ${KBUILD_VMLINUX_MAIN}
56 fi
57}
58
40# Link of vmlinux.o used for section mismatch analysis 59# Link of vmlinux.o used for section mismatch analysis
41# ${1} output file 60# ${1} output file
42modpost_link() 61modpost_link()
43{ 62{
44 ${LD} ${LDFLAGS} -r -o ${1} ${KBUILD_VMLINUX_INIT} \ 63 local objects
45 --start-group ${KBUILD_VMLINUX_MAIN} --end-group 64
65 if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
66 objects="--whole-archive built-in.o"
67 else
68 objects="${KBUILD_VMLINUX_INIT} \
69 --start-group \
70 ${KBUILD_VMLINUX_MAIN} \
71 --end-group"
72 fi
73 ${LD} ${LDFLAGS} -r -o ${1} ${objects}
46} 74}
47 75
48# Link of vmlinux 76# Link of vmlinux
@@ -51,18 +79,36 @@ modpost_link()
51vmlinux_link() 79vmlinux_link()
52{ 80{
53 local lds="${objtree}/${KBUILD_LDS}" 81 local lds="${objtree}/${KBUILD_LDS}"
82 local objects
54 83
55 if [ "${SRCARCH}" != "um" ]; then 84 if [ "${SRCARCH}" != "um" ]; then
56 ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ 85 if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
57 -T ${lds} ${KBUILD_VMLINUX_INIT} \ 86 objects="--whole-archive built-in.o ${1}"
58 --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1} 87 else
88 objects="${KBUILD_VMLINUX_INIT} \
89 --start-group \
90 ${KBUILD_VMLINUX_MAIN} \
91 --end-group \
92 ${1}"
93 fi
94
95 ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
96 -T ${lds} ${objects}
59 else 97 else
60 ${CC} ${CFLAGS_vmlinux} -o ${2} \ 98 if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
61 -Wl,-T,${lds} ${KBUILD_VMLINUX_INIT} \ 99 objects="-Wl,--whole-archive built-in.o ${1}"
62 -Wl,--start-group \ 100 else
63 ${KBUILD_VMLINUX_MAIN} \ 101 objects="${KBUILD_VMLINUX_INIT} \
64 -Wl,--end-group \ 102 -Wl,--start-group \
65 -lutil -lrt -lpthread ${1} 103 ${KBUILD_VMLINUX_MAIN} \
104 -Wl,--end-group \
105 ${1}"
106 fi
107
108 ${CC} ${CFLAGS_vmlinux} -o ${2} \
109 -Wl,-T,${lds} \
110 ${objects} \
111 -lutil -lrt -lpthread
66 rm -f linux 112 rm -f linux
67 fi 113 fi
68} 114}
@@ -119,6 +165,7 @@ cleanup()
119 rm -f .tmp_kallsyms* 165 rm -f .tmp_kallsyms*
120 rm -f .tmp_version 166 rm -f .tmp_version
121 rm -f .tmp_vmlinux* 167 rm -f .tmp_vmlinux*
168 rm -f built-in.o
122 rm -f System.map 169 rm -f System.map
123 rm -f vmlinux 170 rm -f vmlinux
124 rm -f vmlinux.o 171 rm -f vmlinux.o
@@ -162,6 +209,8 @@ case "${KCONFIG_CONFIG}" in
162 . "./${KCONFIG_CONFIG}" 209 . "./${KCONFIG_CONFIG}"
163esac 210esac
164 211
212archive_builtin
213
165#link vmlinux.o 214#link vmlinux.o
166info LD vmlinux.o 215info LD vmlinux.o
167modpost_link vmlinux.o 216modpost_link vmlinux.o
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 48958d3cec9e..bd8349759095 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -888,7 +888,7 @@ static void check_section(const char *modname, struct elf_info *elf,
888 888
889#define DATA_SECTIONS ".data", ".data.rel" 889#define DATA_SECTIONS ".data", ".data.rel"
890#define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \ 890#define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
891 ".kprobes.text" 891 ".kprobes.text", ".cpuidle.text"
892#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \ 892#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
893 ".fixup", ".entry.text", ".exception.text", ".text.*", \ 893 ".fixup", ".entry.text", ".exception.text", ".text.*", \
894 ".coldtext" 894 ".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 42396a74405d..5423a58d1b06 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -363,7 +363,9 @@ is_mcounted_section_name(char const *const txtname)
363 strcmp(".sched.text", txtname) == 0 || 363 strcmp(".sched.text", txtname) == 0 ||
364 strcmp(".spinlock.text", txtname) == 0 || 364 strcmp(".spinlock.text", txtname) == 0 ||
365 strcmp(".irqentry.text", txtname) == 0 || 365 strcmp(".irqentry.text", txtname) == 0 ||
366 strcmp(".softirqentry.text", txtname) == 0 ||
366 strcmp(".kprobes.text", txtname) == 0 || 367 strcmp(".kprobes.text", txtname) == 0 ||
368 strcmp(".cpuidle.text", txtname) == 0 ||
367 strcmp(".text.unlikely", txtname) == 0; 369 strcmp(".text.unlikely", txtname) == 0;
368} 370}
369 371
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 96e2486a6fc4..faac4b10d8ea 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -134,7 +134,9 @@ my %text_sections = (
134 ".sched.text" => 1, 134 ".sched.text" => 1,
135 ".spinlock.text" => 1, 135 ".spinlock.text" => 1,
136 ".irqentry.text" => 1, 136 ".irqentry.text" => 1,
137 ".softirqentry.text" => 1,
137 ".kprobes.text" => 1, 138 ".kprobes.text" => 1,
139 ".cpuidle.text" => 1,
138 ".text.unlikely" => 1, 140 ".text.unlikely" => 1,
139); 141);
140 142
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
index fa79c6d2a5b8..163c720d3f2b 100644
--- a/scripts/spelling.txt
+++ b/scripts/spelling.txt
@@ -629,7 +629,6 @@ mispelt||misspelt
629miximum||maximum 629miximum||maximum
630mmnemonic||mnemonic 630mmnemonic||mnemonic
631mnay||many 631mnay||many
632modeled||modelled
633modulues||modules 632modulues||modules
634monochorome||monochrome 633monochorome||monochrome
635monochromo||monochrome 634monochromo||monochrome
diff --git a/scripts/tags.sh b/scripts/tags.sh
index b3775a9604ea..a2ff3388e5ea 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -263,7 +263,8 @@ exuberant()
263 -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL,ACPI_EXPORT_SYMBOL \ 263 -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL,ACPI_EXPORT_SYMBOL \
264 -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \ 264 -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \
265 -I static,const \ 265 -I static,const \
266 --extra=+f --c-kinds=+px --langmap=c:+.h "${regex[@]}" 266 --extra=+fq --c-kinds=+px --fields=+iaS --langmap=c:+.h \
267 "${regex[@]}"
267 268
268 setup_regex exuberant kconfig 269 setup_regex exuberant kconfig
269 all_kconfigs | xargs $1 -a \ 270 all_kconfigs | xargs $1 -a \
diff --git a/scripts/tracing/ftrace-bisect.sh b/scripts/tracing/ftrace-bisect.sh
new file mode 100755
index 000000000000..9ff8ac5fc53c
--- /dev/null
+++ b/scripts/tracing/ftrace-bisect.sh
@@ -0,0 +1,115 @@
1#!/bin/bash
2#
3# Here's how to use this:
4#
5# This script is used to help find functions that are being traced by function
6# tracer or function graph tracing that causes the machine to reboot, hang, or
7# crash. Here's the steps to take.
8#
9# First, determine if function tracing is working with a single function:
10#
11# (note, if this is a problem with function_graph tracing, then simply
12# replace "function" with "function_graph" in the following steps).
13#
14# # cd /sys/kernel/debug/tracing
15# # echo schedule > set_ftrace_filter
16# # echo function > current_tracer
17#
18# If this works, then we know that something is being traced that shouldn't be.
19#
20# # echo nop > current_tracer
21#
22# # cat available_filter_functions > ~/full-file
23# # ftrace-bisect ~/full-file ~/test-file ~/non-test-file
24# # cat ~/test-file > set_ftrace_filter
25#
26# *** Note *** this will take several minutes. Setting multiple functions is
27# an O(n^2) operation, and we are dealing with thousands of functions. So go
28# have coffee, talk with your coworkers, read facebook. And eventually, this
29# operation will end.
30#
31# # echo function > current_tracer
32#
33# If it crashes, we know that ~/test-file has a bad function.
34#
35# Reboot back to test kernel.
36#
37# # cd /sys/kernel/debug/tracing
38# # mv ~/test-file ~/full-file
39#
40# If it didn't crash.
41#
42# # echo nop > current_tracer
43# # mv ~/non-test-file ~/full-file
44#
45# Get rid of the other test file from previous run (or save them off somewhere).
46# # rm -f ~/test-file ~/non-test-file
47#
48# And start again:
49#
50# # ftrace-bisect ~/full-file ~/test-file ~/non-test-file
51#
52# The good thing is, because this cuts the number of functions in ~/test-file
53# by half, the cat of it into set_ftrace_filter takes half as long each
54# iteration, so don't talk so much at the water cooler the second time.
55#
56# Eventually, if you did this correctly, you will get down to the problem
57# function, and all we need to do is to notrace it.
58#
59# The way to figure out if the problem function is bad, just do:
60#
61# # echo <problem-function> > set_ftrace_notrace
62# # echo > set_ftrace_filter
63# # echo function > current_tracer
64#
65# And if it doesn't crash, we are done.
66#
67# If it does crash, do this again (there's more than one problem function)
68# but you need to echo the problem function(s) into set_ftrace_notrace before
69# enabling function tracing in the above steps. Or if you can compile the
70# kernel, annotate the problem functions with "notrace" and start again.
71#
72
73
74if [ $# -ne 3 ]; then
75 echo 'usage: ftrace-bisect full-file test-file non-test-file'
76 exit
77fi
78
79full=$1
80test=$2
81nontest=$3
82
83x=`cat $full | wc -l`
84if [ $x -eq 1 ]; then
85 echo "There's only one function left, must be the bad one"
86 cat $full
87 exit 0
88fi
89
90let x=$x/2
91let y=$x+1
92
93if [ ! -f $full ]; then
94 echo "$full does not exist"
95 exit 1
96fi
97
98if [ -f $test ]; then
99 echo -n "$test exists, delete it? [y/N]"
100 read a
101 if [ "$a" != "y" -a "$a" != "Y" ]; then
102 exit 1
103 fi
104fi
105
106if [ -f $nontest ]; then
107 echo -n "$nontest exists, delete it? [y/N]"
108 read a
109 if [ "$a" != "y" -a "$a" != "Y" ]; then
110 exit 1
111 fi
112fi
113
114sed -ne "1,${x}p" $full > $test
115sed -ne "$y,\$p" $full > $nontest
diff --git a/scripts/ver_linux b/scripts/ver_linux
index 0d8bd29b1bd6..430b201f3e25 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -1,193 +1,89 @@
1#!/bin/sh 1#!/bin/awk -f
2# Before running this script please ensure that your PATH is 2# Before running this script please ensure that your PATH is
3# typical as you use for compilation/installation. I use 3# typical as you use for compilation/installation. I use
4# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may 4# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may
5# differ on your system. 5# differ on your system.
6#
7echo 'If some fields are empty or look unusual you may have an old version.'
8echo 'Compare to the current minimal requirements in Documentation/Changes.'
9echo ' '
10 6
11uname -a 7BEGIN {
12echo ' ' 8 usage = "If some fields are empty or look unusual you may have an old version.\n"
13 9 usage = usage "Compare to the current minimal requirements in Documentation/Changes.\n"
14gcc -dumpversion 2>&1 | 10 print usage
15awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ 11
16 match($0, /[0-9]+([.]?[0-9]+)+/) 12 system("uname -a")
17 printf("GNU C\t\t\t%s\n", 13 printf("\n")
18 substr($0,RSTART,RLENGTH)) 14
19}' 15 printversion("GNU C", version("gcc -dumpversion 2>&1"))
20 16 printversion("GNU Make", version("make --version 2>&1"))
21make --version 2>&1 | 17 printversion("Binutils", version("ld -v 2>&1"))
22awk '/GNU Make/{ 18 printversion("Util-linux", version("mount --version 2>&1"))
23 match($0, /[0-9]+([.]?[0-9]+)+/) 19 printversion("Mount", version("mount --version 2>&1"))
24 printf("GNU Make\t\t%s\n", 20 printversion("Module-init-tools", version("depmod -V 2>&1"))
25 substr($0,RSTART,RLENGTH)) 21 printversion("E2fsprogs", version("tune2fs 2>&1"))
26}' 22 printversion("Jfsutils", version("fsck.jfs -V 2>&1"))
27 23 printversion("Reiserfsprogs", version("reiserfsck -V 2>&1"))
28ld -v 2>&1 | 24 printversion("Reiser4fsprogs", version("fsck.reiser4 -V 2>&1"))
29awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ 25 printversion("Xfsprogs", version("xfs_db -V 2>&1"))
30 match($0, /[0-9]+([.]?[0-9]+)+/) 26 printversion("Pcmciautils", version("pccardctl -V 2>&1"))
31 printf("Binutils\t\t%s\n", 27 printversion("Pcmcia-cs", version("cardmgr -V 2>&1"))
32 substr($0,RSTART,RLENGTH)) 28 printversion("Quota-tools", version("quota -V 2>&1"))
33}' 29 printversion("PPP", version("pppd --version 2>&1"))
34 30 printversion("Isdn4k-utils", version("isdnctrl 2>&1"))
35mount --version 2>&1 | 31 printversion("Nfs-utils", version("showmount --version 2>&1"))
36awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ 32
37 match($0, /[0-9]+([.]?[0-9]+)+/) 33 if (system("test -r /proc/self/maps") == 0) {
38 $0 = substr($0,RSTART,RLENGTH) 34 while (getline <"/proc/self/maps" > 0) {
39 printf("Util-linux\t\t%s\nMount\t\t\t%s\n",$0,$0) 35 n = split($0, procmaps, "/")
40}' 36 if (/libc.*so$/ && match(procmaps[n], /[0-9]+([.]?[0-9]+)+/)) {
41 37 ver = substr(procmaps[n], RSTART, RLENGTH)
42depmod -V 2>&1 | 38 printversion("Linux C Library", ver)
43awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ 39 break
44 match($0, /[0-9]+([.]?[0-9]+)+/) 40 }
45 printf("Module-init-tools\t%s\n", 41 }
46 substr($0,RSTART,RLENGTH))
47}'
48
49tune2fs 2>&1 |
50awk '/^tune2fs/{
51 match($0, /[0-9]+([.]?[0-9]+)+/)
52 printf("E2fsprogs\t\t%s\n",
53 substr($0,RSTART,RLENGTH))
54}'
55
56fsck.jfs -V 2>&1 |
57awk '/version/{
58 match($0, /[0-9]+([.]?[0-9]+)+/)
59 printf("Jfsutils\t\t%s\n",
60 substr($0,RSTART,RLENGTH))
61}'
62
63reiserfsck -V 2>&1 |
64awk '/^reiserfsck/{
65 match($0, /[0-9]+([.]?[0-9]+)+/)
66 printf("Reiserfsprogs\t\t%s\n",
67 substr($0,RSTART,RLENGTH))
68}'
69
70fsck.reiser4 -V 2>&1 | grep ^fsck.reiser4 | awk \
71'NR==1{print "reiser4progs ", $2}'
72
73xfs_db -V 2>&1 |
74awk '/version/{
75 match($0, /[0-9]+([.]?[0-9]+)+/)
76 printf("Xfsprogs\t\t%s\n",
77 substr($0,RSTART,RLENGTH))
78}'
79
80pccardctl -V 2>&1 |
81awk '/pcmciautils/{
82 match($0, /[0-9]+([.]?[0-9]+)+/)
83 printf("Pcmciautils\t\t%s\n",
84 substr($0,RSTART,RLENGTH))
85}'
86
87cardmgr -V 2>&1| grep version | awk \
88'NR==1{print "pcmcia-cs ", $3}'
89
90quota -V 2>&1 |
91awk '/version/{
92 match($0, /[0-9]+([.]?[0-9]+)+/)
93 printf("Quota-tools\t\t%s\n",
94 substr($0,RSTART,RLENGTH))
95}'
96
97pppd --version 2>&1 |
98awk '/version/{
99 match($0, /[0-9]+([.]?[0-9]+)+/)
100 printf("PPP\t\t\t%s\n",
101 substr($0,RSTART,RLENGTH))
102}'
103
104isdnctrl 2>&1 | grep version | awk \
105'NR==1{print "isdn4k-utils ", $NF}'
106
107showmount --version 2>&1 | grep nfs-utils | awk \
108'NR==1{print "nfs-utils ", $NF}'
109
110test -r /proc/self/maps &&
111sed '
112 /.*libc-\(.*\)\.so$/!d
113 s//Linux C Library\t\t\1/
114 q
115' /proc/self/maps
116
117ldd --version 2>&1 |
118awk '/^ldd/{
119 match($0, /[0-9]+([.]?[0-9]+)+/)
120 printf("Dynamic linker (ldd)\t%s\n",
121 substr($0,RSTART,RLENGTH))
122}'
123
124libcpp=`ldconfig -p 2>/dev/null |
125 awk '/(libg|stdc)[+]+\.so/ {
126 print $NF
127 exit
128 } 42 }
129'`
130test -r "$libcpp" &&
131ls -l $libcpp |
132sed '
133 s!.*so\.!!
134 s!^!Linux C++ Library\t!
135'
136ps --version 2>&1 |
137awk '/version/{
138 match($0, /[0-9]+([.]?[0-9]+)+/)
139 printf("Procps\t\t\t%s\n",
140 substr($0,RSTART,RLENGTH))
141}'
142
143ifconfig --version 2>&1 |
144awk '/tools/{
145 match($0, /[0-9]+([.]?[0-9]+)+/)
146 printf("Net-tools\t\t%s\n",
147 substr($0,RSTART,RLENGTH))
148}'
149
150loadkeys -V 2>&1 |
151awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{
152 match($0, /[0-9]+([.]?[0-9]+)+/)
153 $0 = substr($0,RSTART,RLENGTH)
154 printf("Kbd\t\t\t%s\nConsole-tools\t\t%s\n",$0,$0)
155}'
156 43
157oprofiled --version 2>&1 | awk \ 44 printversion("Dynamic linker (ldd)", version("ldd --version 2>&1"))
158'(NR==1 && ($2 == "oprofile")) {print "oprofile ", $3}'
159 45
160expr --v 2>&1 | 46 while ("ldconfig -p 2>/dev/null" | getline > 0) {
161awk '/^expr/{ 47 if (/(libg|stdc)[+]+\.so/) {
162 match($0, /[0-9]+([.]?[0-9]+)+/) 48 libcpp = $NF
163 printf("Sh-utils\t\t%s\n", 49 break
164 substr($0,RSTART,RLENGTH)) 50 }
165}' 51 }
166 52 if (system("test -r " libcpp) == 0)
167udevadm --version 2>&1 | 53 printversion("Linux C++ Library", version("readlink " libcpp))
168awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ 54
169 match($0, /[0-9]+([.]?[0-9]+)+/) 55 printversion("Procps", version("ps --version 2>&1"))
170 printf("Udev\t\t\t%s\n", 56 printversion("Net-tools", version("ifconfig --version 2>&1"))
171 substr($0,RSTART,RLENGTH)) 57 printversion("Kbd", version("loadkeys -V 2>&1"))
172}' 58 printversion("Console-tools", version("loadkeys -V 2>&1"))
59 printversion("Oprofile", version("oprofiled --version 2>&1"))
60 printversion("Sh-utils", version("expr --v 2>&1"))
61 printversion("Udev", version("udevadm --version 2>&1"))
62 printversion("Wireless-tools", version("iwconfig --version 2>&1"))
63
64 if (system("test -r /proc/modules") == 0) {
65 while ("sort /proc/modules" | getline > 0) {
66 mods = mods sep $1
67 sep = " "
68 }
69 printversion("Modules Loaded", mods)
70 }
71}
173 72
174iwconfig --version 2>&1 | 73function version(cmd, ver) {
175awk '/version/{ 74 while (cmd | getline > 0) {
176 match($0, /[0-9]+([.]?[0-9]+)+/) 75 if (!/ver_linux/ && match($0, /[0-9]+([.]?[0-9]+)+/)) {
177 printf("Wireless-tools\t\t%s\n", 76 ver = substr($0, RSTART, RLENGTH)
178 substr($0,RSTART,RLENGTH)) 77 break
179}' 78 }
79 }
80 close(cmd)
81 return ver
82}
180 83
181test -e /proc/modules && 84function printversion(name, value, ofmt) {
182sort /proc/modules | 85 if (value != "") {
183sed ' 86 ofmt = "%-20s\t%s\n"
184 s/ .*// 87 printf(ofmt, name, value)
185 H 88 }
186${
187 g
188 s/^\n/Modules Loaded\t\t/
189 y/\n/ /
190 q
191} 89}
192 d
193'