diff options
Diffstat (limited to 'scripts')
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 | ||
| 82 | ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),) | 82 | ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),) |
| 83 | lib-target := $(obj)/lib.a | 83 | lib-target := $(obj)/lib.a |
| 84 | obj-y += $(obj)/lib-ksyms.o | ||
| 84 | endif | 85 | endif |
| 85 | 86 | ||
| 86 | ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),) | 87 | ifneq ($(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 | ||
| 161 | cmd_gensymtypes = \ | 162 | # These mirror gensymtypes_S and co below, keep them in synch. |
| 163 | cmd_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 = \ | |||
| 168 | quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ | 170 | quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ |
| 169 | cmd_cc_symtypes_c = \ | 171 | cmd_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 | ||
| 199 | cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< | 201 | cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< |
| 200 | cmd_modversions = \ | 202 | |
| 203 | cmd_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 | |||
| 267 | define rule_cc_o_c | 270 | define 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) |
| 273 | endef | 276 | endef |
| 274 | 277 | ||
| 275 | define rule_as_o_S | 278 | define 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) |
| 278 | endef | 282 | endef |
| 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. | ||
| 331 | cmd_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 | |||
| 343 | quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@ | ||
| 344 | cmd_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 | |||
| 316 | quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@ | 353 | quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@ |
| 317 | cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $< | 354 | cmd_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 | ||
| 322 | quiet_cmd_as_o_S = AS $(quiet_modtag) $@ | 359 | quiet_cmd_as_o_S = AS $(quiet_modtag) $@ |
| 323 | cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< | 360 | |
| 361 | ifndef CONFIG_MODVERSIONS | ||
| 362 | cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< | ||
| 363 | |||
| 364 | else | ||
| 365 | |||
| 366 | ASM_PROTOTYPES := $(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/asm-prototypes.h) | ||
| 367 | |||
| 368 | ifeq ($(ASM_PROTOTYPES),) | ||
| 369 | cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< | ||
| 370 | |||
| 371 | else | ||
| 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 | |||
| 376 | cmd_as_o_S = $(CC) $(a_flags) -c -o $(@D)/.tmp_$(@F) $< | ||
| 377 | |||
| 378 | cmd_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; | ||
| 389 | endif | ||
| 390 | endif | ||
| 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 | # |
| 360 | ifdef builtin-target | 427 | ifdef builtin-target |
| 361 | quiet_cmd_link_o_target = LD $@ | 428 | |
| 429 | ifdef 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 $@ | ||
| 433 | else | ||
| 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 $@ | ||
| 437 | endif | ||
| 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 |
| 363 | cmd_link_o_target = $(if $(strip $(obj-y)),\ | 440 | cmd_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 | # |
| 390 | ifdef lib-target | 467 | ifdef lib-target |
| 391 | quiet_cmd_link_l_target = AR $@ | 468 | quiet_cmd_link_l_target = AR $@ |
| 392 | cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y) | 469 | |
| 470 | ifdef CONFIG_THIN_ARCHIVES | ||
| 471 | cmd_link_l_target = rm -f $@; $(AR) rcsT$(KBUILD_ARFLAGS) $@ $(lib-y) | ||
| 472 | else | ||
| 473 | cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y) | ||
| 474 | endif | ||
| 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 | ||
| 397 | targets += $(lib-target) | 479 | targets += $(lib-target) |
| 480 | |||
| 481 | dummy-object = $(obj)/.lib_exports.o | ||
| 482 | ksyms-lds = $(dot-target).lds | ||
| 483 | ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX | ||
| 484 | ref_prefix = EXTERN(_ | ||
| 485 | else | ||
| 486 | ref_prefix = EXTERN( | ||
| 487 | endif | ||
| 488 | |||
| 489 | quiet_cmd_export_list = EXPORTS $@ | ||
| 490 | cmd_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 | |||
| 500 | targets += $(obj)/lib-ksyms.o | ||
| 501 | |||
| 398 | endif | 502 | endif |
| 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 | |||
| 36 | warning-2 += $(call cc-option, -Wlogical-op) | 36 | warning-2 += $(call cc-option, -Wlogical-op) |
| 37 | warning-2 += $(call cc-option, -Wmissing-field-initializers) | 37 | warning-2 += $(call cc-option, -Wmissing-field-initializers) |
| 38 | warning-2 += $(call cc-option, -Wsign-compare) | 38 | warning-2 += $(call cc-option, -Wsign-compare) |
| 39 | warning-2 += $(call cc-option, -Wmaybe-uninitialized) | ||
| 39 | 40 | ||
| 40 | warning-3 := -Wbad-function-cast | 41 | warning-3 := -Wbad-function-cast |
| 41 | warning-3 += -Wcast-qual | 42 | warning-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 | ||
| 116 | targets += $(modules:.ko=.mod.o) | 116 | targets += $(modules:.ko=.mod.o) |
| 117 | 117 | ||
| 118 | # Step 6), final link of the modules | 118 | ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink) |
| 119 | |||
| 120 | # Step 6), final link of the modules with optional arch pass after final link | ||
| 119 | quiet_cmd_ld_ko_o = LD [M] $@ | 121 | quiet_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 | ||
| 127 | targets += $(modules) | 131 | targets += $(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 | |||
| 14 | ifdef CONFIG_UBSAN_ALIGNMENT | 13 | ifdef CONFIG_UBSAN_ALIGNMENT |
| 15 | CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment) | 14 | CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment) |
| 16 | endif | 15 | endif |
| 16 | |||
| 17 | ifdef CONFIG_UBSAN_NULL | ||
| 18 | CFLAGS_UBSAN += $(call cc-option, -fsanitize=null) | ||
| 19 | endif | ||
| 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) | ||
| 17 | endif | 24 | endif |
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 | |||
| 123 | int insert_extra_deps; | 117 | int insert_extra_deps; |
| 124 | char *target; | 118 | char *target; |
| 125 | char *depfile; | 119 | char *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 | ||
| 244 | static void parse_config_file(const char *map, size_t len) | 238 | static 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 | ||
| 449 | static 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 | |||
| 461 | int main(int argc, char *argv[]) | 433 | int 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 | ||
| 10 | import sys, os, re | 10 | import sys, os, re |
| 11 | from signal import signal, SIGPIPE, SIG_DFL | ||
| 12 | |||
| 13 | signal(SIGPIPE, SIG_DFL) | ||
| 11 | 14 | ||
| 12 | if len(sys.argv) != 3: | 15 | if 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 | ||
| 11 | import argparse | ||
| 11 | import difflib | 12 | import difflib |
| 12 | import os | 13 | import os |
| 13 | import re | 14 | import re |
| 14 | import signal | 15 | import signal |
| 16 | import subprocess | ||
| 15 | import sys | 17 | import sys |
| 16 | from multiprocessing import Pool, cpu_count | 18 | from multiprocessing import Pool, cpu_count |
| 17 | from optparse import OptionParser | ||
| 18 | from subprocess import Popen, PIPE, STDOUT | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | # regex expressions | 21 | # regex expressions |
| 22 | OPERATORS = r"&|\(|\)|\||\!" | 22 | OPERATORS = r"&|\(|\)|\||\!" |
| 23 | FEATURE = r"(?:\w*[A-Z0-9]\w*){2,}" | 23 | SYMBOL = r"(?:\w*[A-Z0-9]\w*){2,}" |
| 24 | DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*" | 24 | DEF = r"^\s*(?:menu){,1}config\s+(" + SYMBOL + r")\s*" |
| 25 | EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+" | 25 | EXPR = r"(?:" + OPERATORS + r"|\s|" + SYMBOL + r")+" |
| 26 | DEFAULT = r"default\s+.*?(?:if\s.+){,1}" | 26 | DEFAULT = r"default\s+.*?(?:if\s.+){,1}" |
| 27 | STMT = r"^\s*(?:if|select|depends\s+on|(?:" + DEFAULT + r"))\s+" + EXPR | 27 | STMT = r"^\s*(?:if|select|depends\s+on|(?:" + DEFAULT + r"))\s+" + EXPR |
| 28 | SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")" | 28 | SOURCE_SYMBOL = r"(?:\W|\b)+[D]{,1}CONFIG_(" + SYMBOL + r")" |
| 29 | 29 | ||
| 30 | # regex objects | 30 | # regex objects |
| 31 | REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") | 31 | REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") |
| 32 | REGEX_FEATURE = re.compile(r'(?!\B)' + FEATURE + r'(?!\B)') | 32 | REGEX_SYMBOL = re.compile(r'(?!\B)' + SYMBOL + r'(?!\B)') |
| 33 | REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE) | 33 | REGEX_SOURCE_SYMBOL = re.compile(SOURCE_SYMBOL) |
| 34 | REGEX_KCONFIG_DEF = re.compile(DEF) | 34 | REGEX_KCONFIG_DEF = re.compile(DEF) |
| 35 | REGEX_KCONFIG_EXPR = re.compile(EXPR) | 35 | REGEX_KCONFIG_EXPR = re.compile(EXPR) |
| 36 | REGEX_KCONFIG_STMT = re.compile(STMT) | 36 | REGEX_KCONFIG_STMT = re.compile(STMT) |
| 37 | REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") | 37 | REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") |
| 38 | REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$") | 38 | REGEX_FILTER_SYMBOLS = re.compile(r"[A-Za-z0-9]$") |
| 39 | REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") | 39 | REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") |
| 40 | REGEX_QUOTES = re.compile("(\"(.*?)\")") | 40 | REGEX_QUOTES = re.compile("(\"(.*?)\")") |
| 41 | 41 | ||
| 42 | 42 | ||
| 43 | def parse_options(): | 43 | def 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 | ||
| 115 | def main(): | 116 | def 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 | |||
| 205 | def reset(commit): | ||
| 206 | """Reset current git tree to %commit.""" | ||
| 207 | execute(["git", "reset", "--hard", commit]) | ||
| 199 | 208 | ||
| 200 | 209 | ||
| 201 | def yel(string): | 210 | def 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 | ||
| 208 | def red(string): | 217 | def 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 | ||
| 215 | def execute(cmd): | 224 | def 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 | ||
| 224 | def find_commits(symbol, diff): | 234 | def 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 | ||
| 231 | def tree_is_dirty(): | 242 | def 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 | ||
| 241 | def get_head(): | 252 | def 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 | ||
| 247 | def partition(lst, size): | 258 | def 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 | ||
| 252 | def init_worker(): | 263 | def 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 | ||
| 257 | def find_sims(symbol, ignore, defined = []): | 268 | def 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 = []): | |||
| 279 | def get_files(): | 290 | def 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 | ||
| 364 | def parse_source_files(source_files): | 374 | def 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 | ||
| 373 | def parse_source_file(sfile): | 383 | def 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 | ||
| 396 | def get_features_in_line(line): | 406 | def 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 | ||
| 401 | def parse_kconfig_files(args): | 411 | def 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 | ||
| 420 | def parse_kconfig_file(kfile): | 430 | def 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; | |||
| 54 | my $spelling_file = "$D/spelling.txt"; | 54 | my $spelling_file = "$D/spelling.txt"; |
| 55 | my $codespell = 0; | 55 | my $codespell = 0; |
| 56 | my $codespellfile = "/usr/share/codespell/dictionary.txt"; | 56 | my $codespellfile = "/usr/share/codespell/dictionary.txt"; |
| 57 | my $conststructsfile = "$D/const_structs.checkpatch"; | ||
| 57 | my $color = 1; | 58 | my $color = 1; |
| 58 | my $allow_c99_comments = 1; | 59 | my $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 | ||
| 549 | our %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 | ||
| 569 | our $mode_perms_string_search = ""; | ||
| 570 | foreach 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 | |||
| 544 | our $allowed_asm_includes = qr{(?x: | 575 | our $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 | ||
| 632 | my $const_structs = ""; | ||
| 633 | if (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 | |||
| 601 | sub build_types { | 655 | sub 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 | ||
| 761 | sub 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 | |||
| 707 | my $camelcase_seeded = 0; | 771 | my $camelcase_seeded = 0; |
| 708 | sub seed_camelcase_includes { | 772 | sub 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 | |||
| 15 | virtual report | 15 | virtual report |
| 16 | 16 | ||
| 17 | @depends on patch@ | 17 | @depends on patch@ |
| 18 | expression from,to,size,flag; | 18 | expression from,to,size; |
| 19 | identifier l1,l2; | 19 | identifier 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@ |
| 40 | expression from,to,size,flag; | 40 | expression from,to,size; |
| 41 | position p; | 41 | position p; |
| 42 | statement S1,S2; | 42 | statement 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@ |
| 19 | expression ret; | 19 | expression ret; |
| 20 | position p; | ||
| 20 | @@ | 21 | @@ |
| 21 | ( | 22 | ( |
| 22 | ret = \(pm_runtime_idle\| | 23 | ret@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@ |
| 51 | identifier pm_runtime_api; | 52 | identifier pm_runtime_api; |
| 52 | expression ret; | 53 | expression ret; |
| 54 | position runtime_bad_err_handle.p; | ||
| 53 | @@ | 55 | @@ |
| 54 | ( | 56 | ( |
| 55 | ret = pm_runtime_api(...); | 57 | ret@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@ |
| 66 | identifier pm_runtime_api; | 68 | identifier pm_runtime_api; |
| 67 | expression ret; | 69 | expression ret; |
| 70 | position runtime_bad_err_handle.p; | ||
| 68 | @@ | 71 | @@ |
| 69 | ( | 72 | ( |
| 70 | ret = pm_runtime_api(...); | 73 | ret@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@ |
| 82 | position p1, p2; | 85 | position p1, p2; |
| 83 | identifier pm_runtime_api; | 86 | identifier pm_runtime_api; |
| 84 | expression ret; | 87 | expression ret; |
| 88 | position runtime_bad_err_handle.p; | ||
| 85 | @@ | 89 | @@ |
| 86 | ( | 90 | ( |
| 87 | ret = pm_runtime_api@p1(...); | 91 | ret@p = pm_runtime_api@p1(...); |
| 88 | ... | 92 | ... |
| 89 | IS_ERR_VALUE@p2(ret) | 93 | IS_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 | |||
| 44 | virtual org | ||
| 45 | virtual report | ||
| 46 | |||
| 47 | @cond@ | ||
| 48 | statement S1; | ||
| 49 | position p; | ||
| 50 | @@ | ||
| 51 | |||
| 52 | * if@p (...) S1 else S1 | ||
| 53 | |||
| 54 | @script:python depends on org@ | ||
| 55 | p << cond.p; | ||
| 56 | @@ | ||
| 57 | |||
| 58 | cocci.print_main("WARNING: possible condition with no effect (if == else)",p) | ||
| 59 | |||
| 60 | @script:python depends on report@ | ||
| 61 | p << cond.p; | ||
| 62 | @@ | ||
| 63 | |||
| 64 | coccilib.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 @@ | |||
| 1 | acpi_dock_ops | ||
| 2 | address_space_operations | ||
| 3 | backlight_ops | ||
| 4 | block_device_operations | ||
| 5 | clk_ops | ||
| 6 | comedi_lrange | ||
| 7 | component_ops | ||
| 8 | dentry_operations | ||
| 9 | dev_pm_ops | ||
| 10 | dma_map_ops | ||
| 11 | driver_info | ||
| 12 | drm_connector_funcs | ||
| 13 | drm_encoder_funcs | ||
| 14 | drm_encoder_helper_funcs | ||
| 15 | ethtool_ops | ||
| 16 | extent_io_ops | ||
| 17 | file_lock_operations | ||
| 18 | file_operations | ||
| 19 | hv_ops | ||
| 20 | ide_dma_ops | ||
| 21 | ide_port_ops | ||
| 22 | inode_operations | ||
| 23 | intel_dvo_dev_ops | ||
| 24 | irq_domain_ops | ||
| 25 | item_operations | ||
| 26 | iwl_cfg | ||
| 27 | iwl_ops | ||
| 28 | kgdb_arch | ||
| 29 | kgdb_io | ||
| 30 | kset_uevent_ops | ||
| 31 | lock_manager_operations | ||
| 32 | machine_desc | ||
| 33 | microcode_ops | ||
| 34 | mlxsw_reg_info | ||
| 35 | mtrr_ops | ||
| 36 | neigh_ops | ||
| 37 | net_device_ops | ||
| 38 | nlmsvc_binding | ||
| 39 | nvkm_device_chip | ||
| 40 | of_device_id | ||
| 41 | pci_raw_ops | ||
| 42 | pipe_buf_operations | ||
| 43 | platform_hibernation_ops | ||
| 44 | platform_suspend_ops | ||
| 45 | proto_ops | ||
| 46 | regmap_access_table | ||
| 47 | rpc_pipe_ops | ||
| 48 | rtc_class_ops | ||
| 49 | sd_desc | ||
| 50 | seq_operations | ||
| 51 | sirfsoc_padmux | ||
| 52 | snd_ac97_build_ops | ||
| 53 | snd_soc_component_driver | ||
| 54 | soc_pcmcia_socket_ops | ||
| 55 | stacktrace_ops | ||
| 56 | sysfs_ops | ||
| 57 | tty_operations | ||
| 58 | uart_ops | ||
| 59 | usb_mon_operations | ||
| 60 | v4l2_ctrl_ops | ||
| 61 | v4l2_ioctl_ops | ||
| 62 | vm_operations_struct | ||
| 63 | wacom_features | ||
| 64 | wd_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 | ||
| 23 | int plugin_is_GPL_compatible; | 23 | __visible int plugin_is_GPL_compatible; |
| 24 | 24 | ||
| 25 | static struct plugin_info cyc_complexity_plugin_info = { | 25 | static 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 | ||
| 52 | int 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 | |||
| 82 | static GTY(()) tree latent_entropy_decl; | ||
| 83 | |||
| 84 | static struct plugin_info latent_entropy_plugin_info = { | ||
| 85 | .version = "201606141920vanilla", | ||
| 86 | .help = "disable\tturn off latent entropy instrumentation\n", | ||
| 87 | }; | ||
| 88 | |||
| 89 | static 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 | */ | ||
| 95 | static 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 | |||
| 110 | static 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 | |||
| 122 | static 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 | |||
| 258 | static 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 | |||
| 271 | static void register_attributes(void *event_data __unused, void *data __unused) | ||
| 272 | { | ||
| 273 | register_attribute(&latent_entropy_attr); | ||
| 274 | } | ||
| 275 | |||
| 276 | static 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 | |||
| 292 | static 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 | */ | ||
| 314 | static 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 | |||
| 347 | static 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 | |||
| 353 | static 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 | |||
| 367 | static 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 | |||
| 396 | static 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 | |||
| 418 | static 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 | |||
| 444 | static 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 | |||
| 490 | static 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 | |||
| 514 | static 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 | |||
| 553 | static 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 = >_ggc_mx_tree_node, | ||
| 607 | .pchw = >_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 *)>_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 | ||
| 24 | int plugin_is_GPL_compatible; | 24 | __visible int plugin_is_GPL_compatible; |
| 25 | 25 | ||
| 26 | tree sancov_fndecl; | 26 | tree 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 | ||
| 89 | int 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 | ||
| 3 | echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" | 3 | echo "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" |
| 4 | if [ "$?" -eq "0" ] ; then | 4 | if [ "$?" -eq "0" ] ; then |
| 5 | echo y | 5 | echo y |
| 6 | else | 6 | else |
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 | ||
| 99 | list_parse() { | 99 | list_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; | |||
| 212 | my $type_constant = '\%([-_\w]+)'; | 212 | my $type_constant = '\%([-_\w]+)'; |
| 213 | my $type_func = '(\w+)\(\)'; | 213 | my $type_func = '(\w+)\(\)'; |
| 214 | my $type_param = '\@(\w+)'; | 214 | my $type_param = '\@(\w+)'; |
| 215 | my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params | ||
| 215 | my $type_struct = '\&((struct\s*)*[_\w]+)'; | 216 | my $type_struct = '\&((struct\s*)*[_\w]+)'; |
| 216 | my $type_struct_xml = '\\&((struct\s*)*[_\w]+)'; | 217 | my $type_struct_xml = '\\&((struct\s*)*[_\w]+)'; |
| 217 | my $type_env = '(\$\w+)'; | 218 | my $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*\* ?'; | |||
| 412 | my $doc_decl = $doc_com . '(\w+)'; | 414 | my $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 |
| 414 | my $doc_sect = $doc_com . | 416 | my $doc_sect = $doc_com . |
| 415 | '\s*(\@\w+|description|context|returns?|notes?|examples?)\s*:(.*)'; | 417 | '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)'; |
| 416 | my $doc_content = $doc_com_body . '(.*)'; | 418 | my $doc_content = $doc_com_body . '(.*)'; |
| 417 | my $doc_block = $doc_com . 'DOC:\s*(.*)?'; | 419 | my $doc_block = $doc_com . 'DOC:\s*(.*)?'; |
| 418 | my $doc_inline_start = '^\s*/\*\*\s*$'; | 420 | my $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 | # | ||
| 48 | archive_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 |
| 42 | modpost_link() | 61 | modpost_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() | |||
| 51 | vmlinux_link() | 79 | vmlinux_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}" |
| 163 | esac | 210 | esac |
| 164 | 211 | ||
| 212 | archive_builtin | ||
| 213 | |||
| 165 | #link vmlinux.o | 214 | #link vmlinux.o |
| 166 | info LD vmlinux.o | 215 | info LD vmlinux.o |
| 167 | modpost_link vmlinux.o | 216 | modpost_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 | |||
| 629 | miximum||maximum | 629 | miximum||maximum |
| 630 | mmnemonic||mnemonic | 630 | mmnemonic||mnemonic |
| 631 | mnay||many | 631 | mnay||many |
| 632 | modeled||modelled | ||
| 633 | modulues||modules | 632 | modulues||modules |
| 634 | monochorome||monochrome | 633 | monochorome||monochrome |
| 635 | monochromo||monochrome | 634 | monochromo||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 | |||
| 74 | if [ $# -ne 3 ]; then | ||
| 75 | echo 'usage: ftrace-bisect full-file test-file non-test-file' | ||
| 76 | exit | ||
| 77 | fi | ||
| 78 | |||
| 79 | full=$1 | ||
| 80 | test=$2 | ||
| 81 | nontest=$3 | ||
| 82 | |||
| 83 | x=`cat $full | wc -l` | ||
| 84 | if [ $x -eq 1 ]; then | ||
| 85 | echo "There's only one function left, must be the bad one" | ||
| 86 | cat $full | ||
| 87 | exit 0 | ||
| 88 | fi | ||
| 89 | |||
| 90 | let x=$x/2 | ||
| 91 | let y=$x+1 | ||
| 92 | |||
| 93 | if [ ! -f $full ]; then | ||
| 94 | echo "$full does not exist" | ||
| 95 | exit 1 | ||
| 96 | fi | ||
| 97 | |||
| 98 | if [ -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 | ||
| 104 | fi | ||
| 105 | |||
| 106 | if [ -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 | ||
| 112 | fi | ||
| 113 | |||
| 114 | sed -ne "1,${x}p" $full > $test | ||
| 115 | sed -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 | # | ||
| 7 | echo 'If some fields are empty or look unusual you may have an old version.' | ||
| 8 | echo 'Compare to the current minimal requirements in Documentation/Changes.' | ||
| 9 | echo ' ' | ||
| 10 | 6 | ||
| 11 | uname -a | 7 | BEGIN { |
| 12 | echo ' ' | 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" | |
| 14 | gcc -dumpversion 2>&1 | | 10 | print usage |
| 15 | awk '/[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")) | |
| 21 | make --version 2>&1 | | 17 | printversion("Binutils", version("ld -v 2>&1")) |
| 22 | awk '/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")) | |
| 28 | ld -v 2>&1 | | 24 | printversion("Reiser4fsprogs", version("fsck.reiser4 -V 2>&1")) |
| 29 | awk '/[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")) | |
| 35 | mount --version 2>&1 | | 31 | printversion("Nfs-utils", version("showmount --version 2>&1")) |
| 36 | awk '/[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) | |
| 42 | depmod -V 2>&1 | | 38 | printversion("Linux C Library", ver) |
| 43 | awk '/[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 | |||
| 49 | tune2fs 2>&1 | | ||
| 50 | awk '/^tune2fs/{ | ||
| 51 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 52 | printf("E2fsprogs\t\t%s\n", | ||
| 53 | substr($0,RSTART,RLENGTH)) | ||
| 54 | }' | ||
| 55 | |||
| 56 | fsck.jfs -V 2>&1 | | ||
| 57 | awk '/version/{ | ||
| 58 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 59 | printf("Jfsutils\t\t%s\n", | ||
| 60 | substr($0,RSTART,RLENGTH)) | ||
| 61 | }' | ||
| 62 | |||
| 63 | reiserfsck -V 2>&1 | | ||
| 64 | awk '/^reiserfsck/{ | ||
| 65 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 66 | printf("Reiserfsprogs\t\t%s\n", | ||
| 67 | substr($0,RSTART,RLENGTH)) | ||
| 68 | }' | ||
| 69 | |||
| 70 | fsck.reiser4 -V 2>&1 | grep ^fsck.reiser4 | awk \ | ||
| 71 | 'NR==1{print "reiser4progs ", $2}' | ||
| 72 | |||
| 73 | xfs_db -V 2>&1 | | ||
| 74 | awk '/version/{ | ||
| 75 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 76 | printf("Xfsprogs\t\t%s\n", | ||
| 77 | substr($0,RSTART,RLENGTH)) | ||
| 78 | }' | ||
| 79 | |||
| 80 | pccardctl -V 2>&1 | | ||
| 81 | awk '/pcmciautils/{ | ||
| 82 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 83 | printf("Pcmciautils\t\t%s\n", | ||
| 84 | substr($0,RSTART,RLENGTH)) | ||
| 85 | }' | ||
| 86 | |||
| 87 | cardmgr -V 2>&1| grep version | awk \ | ||
| 88 | 'NR==1{print "pcmcia-cs ", $3}' | ||
| 89 | |||
| 90 | quota -V 2>&1 | | ||
| 91 | awk '/version/{ | ||
| 92 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 93 | printf("Quota-tools\t\t%s\n", | ||
| 94 | substr($0,RSTART,RLENGTH)) | ||
| 95 | }' | ||
| 96 | |||
| 97 | pppd --version 2>&1 | | ||
| 98 | awk '/version/{ | ||
| 99 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 100 | printf("PPP\t\t\t%s\n", | ||
| 101 | substr($0,RSTART,RLENGTH)) | ||
| 102 | }' | ||
| 103 | |||
| 104 | isdnctrl 2>&1 | grep version | awk \ | ||
| 105 | 'NR==1{print "isdn4k-utils ", $NF}' | ||
| 106 | |||
| 107 | showmount --version 2>&1 | grep nfs-utils | awk \ | ||
| 108 | 'NR==1{print "nfs-utils ", $NF}' | ||
| 109 | |||
| 110 | test -r /proc/self/maps && | ||
| 111 | sed ' | ||
| 112 | /.*libc-\(.*\)\.so$/!d | ||
| 113 | s//Linux C Library\t\t\1/ | ||
| 114 | q | ||
| 115 | ' /proc/self/maps | ||
| 116 | |||
| 117 | ldd --version 2>&1 | | ||
| 118 | awk '/^ldd/{ | ||
| 119 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 120 | printf("Dynamic linker (ldd)\t%s\n", | ||
| 121 | substr($0,RSTART,RLENGTH)) | ||
| 122 | }' | ||
| 123 | |||
| 124 | libcpp=`ldconfig -p 2>/dev/null | | ||
| 125 | awk '/(libg|stdc)[+]+\.so/ { | ||
| 126 | print $NF | ||
| 127 | exit | ||
| 128 | } | 42 | } |
| 129 | '` | ||
| 130 | test -r "$libcpp" && | ||
| 131 | ls -l $libcpp | | ||
| 132 | sed ' | ||
| 133 | s!.*so\.!! | ||
| 134 | s!^!Linux C++ Library\t! | ||
| 135 | ' | ||
| 136 | ps --version 2>&1 | | ||
| 137 | awk '/version/{ | ||
| 138 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 139 | printf("Procps\t\t\t%s\n", | ||
| 140 | substr($0,RSTART,RLENGTH)) | ||
| 141 | }' | ||
| 142 | |||
| 143 | ifconfig --version 2>&1 | | ||
| 144 | awk '/tools/{ | ||
| 145 | match($0, /[0-9]+([.]?[0-9]+)+/) | ||
| 146 | printf("Net-tools\t\t%s\n", | ||
| 147 | substr($0,RSTART,RLENGTH)) | ||
| 148 | }' | ||
| 149 | |||
| 150 | loadkeys -V 2>&1 | | ||
| 151 | awk '/[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 | ||
| 157 | oprofiled --version 2>&1 | awk \ | 44 | printversion("Dynamic linker (ldd)", version("ldd --version 2>&1")) |
| 158 | '(NR==1 && ($2 == "oprofile")) {print "oprofile ", $3}' | ||
| 159 | 45 | ||
| 160 | expr --v 2>&1 | | 46 | while ("ldconfig -p 2>/dev/null" | getline > 0) { |
| 161 | awk '/^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) | |
| 167 | udevadm --version 2>&1 | | 53 | printversion("Linux C++ Library", version("readlink " libcpp)) |
| 168 | awk '/[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 | ||
| 174 | iwconfig --version 2>&1 | | 73 | function version(cmd, ver) { |
| 175 | awk '/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 | ||
| 181 | test -e /proc/modules && | 84 | function printversion(name, value, ofmt) { |
| 182 | sort /proc/modules | | 85 | if (value != "") { |
| 183 | sed ' | 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 | ' | ||
