diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/Kbuild.include | 65 | ||||
-rw-r--r-- | scripts/Makefile.build | 27 | ||||
-rw-r--r-- | scripts/Makefile.clean | 10 | ||||
-rw-r--r-- | scripts/Makefile.modinst | 10 | ||||
-rw-r--r-- | scripts/Makefile.modpost | 19 | ||||
-rw-r--r-- | scripts/basic/fixdep.c | 14 | ||||
-rwxr-xr-x | scripts/checkconfig.pl | 65 | ||||
-rw-r--r-- | scripts/genksyms/genksyms.c | 843 | ||||
-rw-r--r-- | scripts/genksyms/genksyms.h | 57 | ||||
-rw-r--r-- | scripts/kconfig/Makefile | 6 | ||||
-rw-r--r-- | scripts/kconfig/confdata.c | 2 | ||||
-rw-r--r-- | scripts/kconfig/lxdialog/Makefile | 6 | ||||
-rw-r--r-- | scripts/mkmakefile | 8 | ||||
-rw-r--r-- | scripts/mod/file2alias.c | 17 | ||||
-rw-r--r-- | scripts/mod/mk_elfconfig.c | 4 | ||||
-rw-r--r-- | scripts/mod/modpost.c | 698 | ||||
-rw-r--r-- | scripts/mod/modpost.h | 25 | ||||
-rw-r--r-- | scripts/mod/sumversion.c | 32 | ||||
-rw-r--r-- | scripts/namespace.pl | 4 | ||||
-rw-r--r-- | scripts/package/Makefile | 20 | ||||
-rw-r--r-- | scripts/reference_discarded.pl | 112 | ||||
-rw-r--r-- | scripts/reference_init.pl | 108 |
22 files changed, 1139 insertions, 1013 deletions
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 0168d6c37075..59620b1554e0 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include | |||
@@ -44,6 +44,43 @@ define filechk | |||
44 | fi | 44 | fi |
45 | endef | 45 | endef |
46 | 46 | ||
47 | ###### | ||
48 | # gcc support functions | ||
49 | # See documentation in Documentation/kbuild/makefiles.txt | ||
50 | |||
51 | # as-option | ||
52 | # Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,) | ||
53 | |||
54 | as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \ | ||
55 | -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \ | ||
56 | else echo "$(2)"; fi ;) | ||
57 | |||
58 | # cc-option | ||
59 | # Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586) | ||
60 | |||
61 | cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ | ||
62 | > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) | ||
63 | |||
64 | # cc-option-yn | ||
65 | # Usage: flag := $(call cc-option-yn, -march=winchip-c6) | ||
66 | cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ | ||
67 | > /dev/null 2>&1; then echo "y"; else echo "n"; fi;) | ||
68 | |||
69 | # cc-option-align | ||
70 | # Prefix align with either -falign or -malign | ||
71 | cc-option-align = $(subst -functions=0,,\ | ||
72 | $(call cc-option,-falign-functions=0,-malign-functions=0)) | ||
73 | |||
74 | # cc-version | ||
75 | # Usage gcc-ver := $(call cc-version, $(CC)) | ||
76 | cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \ | ||
77 | $(if $(1), $(1), $(CC))) | ||
78 | |||
79 | # cc-ifversion | ||
80 | # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) | ||
81 | cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \ | ||
82 | echo $(3); fi;) | ||
83 | |||
47 | ### | 84 | ### |
48 | # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= | 85 | # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= |
49 | # Usage: | 86 | # Usage: |
@@ -51,8 +88,7 @@ endef | |||
51 | build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj | 88 | build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj |
52 | 89 | ||
53 | # If quiet is set, only print short version of command | 90 | # If quiet is set, only print short version of command |
54 | cmd = @$(if $($(quiet)cmd_$(1)),\ | 91 | cmd = @$(echo-cmd) $(cmd_$(1)) |
55 | echo ' $(call escsq,$($(quiet)cmd_$(1)))' &&) $(cmd_$(1)) | ||
56 | 92 | ||
57 | # Add $(obj)/ for paths that is not absolute | 93 | # Add $(obj)/ for paths that is not absolute |
58 | objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o))) | 94 | objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o))) |
@@ -75,30 +111,33 @@ endif | |||
75 | echo-cmd = $(if $($(quiet)cmd_$(1)), \ | 111 | echo-cmd = $(if $($(quiet)cmd_$(1)), \ |
76 | echo ' $(call escsq,$($(quiet)cmd_$(1)))';) | 112 | echo ' $(call escsq,$($(quiet)cmd_$(1)))';) |
77 | 113 | ||
114 | make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) | ||
115 | |||
78 | # function to only execute the passed command if necessary | 116 | # function to only execute the passed command if necessary |
79 | # >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file | 117 | # >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file |
80 | # note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars | 118 | # note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars |
81 | # | 119 | # |
82 | if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \ | 120 | if_changed = $(if $(strip $(filter-out $(PHONY),$?) \ |
121 | $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \ | ||
83 | @set -e; \ | 122 | @set -e; \ |
84 | $(echo-cmd) \ | 123 | $(echo-cmd) $(cmd_$(1)); \ |
85 | $(cmd_$(1)); \ | 124 | echo 'cmd_$@ := $(make-cmd)' > $(@D)/.$(@F).cmd) |
86 | echo 'cmd_$@ := $(subst $$,$$$$,$(call escsq,$(cmd_$(1))))' > $(@D)/.$(@F).cmd) | ||
87 | 125 | ||
88 | # execute the command and also postprocess generated .d dependencies | 126 | # execute the command and also postprocess generated .d dependencies |
89 | # file | 127 | # file |
90 | if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\ | 128 | if_changed_dep = $(if $(strip $(filter-out $(PHONY),$?) \ |
91 | $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \ | 129 | $(filter-out FORCE $(wildcard $^),$^) \ |
130 | $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \ | ||
92 | @set -e; \ | 131 | @set -e; \ |
93 | $(echo-cmd) \ | 132 | $(echo-cmd) $(cmd_$(1)); \ |
94 | $(cmd_$(1)); \ | 133 | scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(@D)/.$(@F).tmp; \ |
95 | scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \ | ||
96 | rm -f $(depfile); \ | 134 | rm -f $(depfile); \ |
97 | mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd) | 135 | mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd) |
98 | 136 | ||
99 | # Usage: $(call if_changed_rule,foo) | 137 | # Usage: $(call if_changed_rule,foo) |
100 | # will check if $(cmd_foo) changed, or any of the prequisites changed, | 138 | # will check if $(cmd_foo) changed, or any of the prequisites changed, |
101 | # and if so will execute $(rule_foo) | 139 | # and if so will execute $(rule_foo) |
102 | if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\ | 140 | if_changed_rule = $(if $(strip $(filter-out $(PHONY),$?) \ |
141 | $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\ | ||
103 | @set -e; \ | 142 | @set -e; \ |
104 | $(rule_$(1))) | 143 | $(rule_$(1))) |
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index c33e62bde6b0..e48e60da3040 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build | |||
@@ -4,17 +4,18 @@ | |||
4 | 4 | ||
5 | src := $(obj) | 5 | src := $(obj) |
6 | 6 | ||
7 | .PHONY: __build | 7 | PHONY := __build |
8 | __build: | 8 | __build: |
9 | 9 | ||
10 | # Read .config if it exist, otherwise ignore | 10 | # Read .config if it exist, otherwise ignore |
11 | -include .config | 11 | -include .config |
12 | 12 | ||
13 | include scripts/Kbuild.include | ||
14 | |||
13 | # The filename Kbuild has precedence over Makefile | 15 | # The filename Kbuild has precedence over Makefile |
14 | kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) | 16 | kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) |
15 | include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) | 17 | include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) |
16 | 18 | ||
17 | include scripts/Kbuild.include | ||
18 | include scripts/Makefile.lib | 19 | include scripts/Makefile.lib |
19 | 20 | ||
20 | ifdef host-progs | 21 | ifdef host-progs |
@@ -128,7 +129,7 @@ $(multi-objs-y:.o=.s) : modname = $(modname-multi) | |||
128 | $(multi-objs-y:.o=.lst) : modname = $(modname-multi) | 129 | $(multi-objs-y:.o=.lst) : modname = $(modname-multi) |
129 | 130 | ||
130 | quiet_cmd_cc_s_c = CC $(quiet_modtag) $@ | 131 | quiet_cmd_cc_s_c = CC $(quiet_modtag) $@ |
131 | cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< | 132 | cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $< |
132 | 133 | ||
133 | %.s: %.c FORCE | 134 | %.s: %.c FORCE |
134 | $(call if_changed_dep,cc_s_c) | 135 | $(call if_changed_dep,cc_s_c) |
@@ -165,7 +166,7 @@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< | |||
165 | cmd_modversions = \ | 166 | cmd_modversions = \ |
166 | if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ | 167 | if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ |
167 | $(CPP) -D__GENKSYMS__ $(c_flags) $< \ | 168 | $(CPP) -D__GENKSYMS__ $(c_flags) $< \ |
168 | | $(GENKSYMS) \ | 169 | | $(GENKSYMS) -a $(ARCH) \ |
169 | > $(@D)/.tmp_$(@F:.o=.ver); \ | 170 | > $(@D)/.tmp_$(@F:.o=.ver); \ |
170 | \ | 171 | \ |
171 | $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ | 172 | $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ |
@@ -177,12 +178,10 @@ cmd_modversions = \ | |||
177 | endif | 178 | endif |
178 | 179 | ||
179 | define rule_cc_o_c | 180 | define rule_cc_o_c |
180 | $(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \ | 181 | $(call echo-cmd,checksrc) $(cmd_checksrc) \ |
181 | $(cmd_checksrc) \ | 182 | $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ |
182 | $(if $($(quiet)cmd_cc_o_c),echo ' $(call escsq,$($(quiet)cmd_cc_o_c))';) \ | ||
183 | $(cmd_cc_o_c); \ | ||
184 | $(cmd_modversions) \ | 183 | $(cmd_modversions) \ |
185 | scripts/basic/fixdep $(depfile) $@ '$(call escsq,$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp; \ | 184 | scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > $(@D)/.$(@F).tmp; \ |
186 | rm -f $(depfile); \ | 185 | rm -f $(depfile); \ |
187 | mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd | 186 | mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd |
188 | endef | 187 | endef |
@@ -309,14 +308,14 @@ targets += $(multi-used-y) $(multi-used-m) | |||
309 | # Descending | 308 | # Descending |
310 | # --------------------------------------------------------------------------- | 309 | # --------------------------------------------------------------------------- |
311 | 310 | ||
312 | .PHONY: $(subdir-ym) | 311 | PHONY += $(subdir-ym) |
313 | $(subdir-ym): | 312 | $(subdir-ym): |
314 | $(Q)$(MAKE) $(build)=$@ | 313 | $(Q)$(MAKE) $(build)=$@ |
315 | 314 | ||
316 | # Add FORCE to the prequisites of a target to force it to be always rebuilt. | 315 | # Add FORCE to the prequisites of a target to force it to be always rebuilt. |
317 | # --------------------------------------------------------------------------- | 316 | # --------------------------------------------------------------------------- |
318 | 317 | ||
319 | .PHONY: FORCE | 318 | PHONY += FORCE |
320 | 319 | ||
321 | FORCE: | 320 | FORCE: |
322 | 321 | ||
@@ -331,3 +330,9 @@ cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) | |||
331 | ifneq ($(cmd_files),) | 330 | ifneq ($(cmd_files),) |
332 | include $(cmd_files) | 331 | include $(cmd_files) |
333 | endif | 332 | endif |
333 | |||
334 | |||
335 | # Declare the contents of the .PHONY variable as phony. We keep that | ||
336 | # information in a variable se we can use it in if_changed and friends. | ||
337 | |||
338 | .PHONY: $(PHONY) | ||
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index 8974ea5fc878..cff33498fa16 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | src := $(obj) | 5 | src := $(obj) |
6 | 6 | ||
7 | .PHONY: __clean | 7 | PHONY := __clean |
8 | __clean: | 8 | __clean: |
9 | 9 | ||
10 | # Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir | 10 | # Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir |
@@ -87,10 +87,16 @@ endif | |||
87 | # Descending | 87 | # Descending |
88 | # --------------------------------------------------------------------------- | 88 | # --------------------------------------------------------------------------- |
89 | 89 | ||
90 | .PHONY: $(subdir-ymn) | 90 | PHONY += $(subdir-ymn) |
91 | $(subdir-ymn): | 91 | $(subdir-ymn): |
92 | $(Q)$(MAKE) $(clean)=$@ | 92 | $(Q)$(MAKE) $(clean)=$@ |
93 | 93 | ||
94 | # If quiet is set, only print short version of command | 94 | # If quiet is set, only print short version of command |
95 | 95 | ||
96 | cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) | 96 | cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) |
97 | |||
98 | |||
99 | # Declare the contents of the .PHONY variable as phony. We keep that | ||
100 | # information in a variable se we can use it in if_changed and friends. | ||
101 | |||
102 | .PHONY: $(PHONY) | ||
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index 23fd1bdc25ce..2686dd5dce8c 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst | |||
@@ -2,7 +2,7 @@ | |||
2 | # Installing modules | 2 | # Installing modules |
3 | # ========================================================================== | 3 | # ========================================================================== |
4 | 4 | ||
5 | .PHONY: __modinst | 5 | PHONY := __modinst |
6 | __modinst: | 6 | __modinst: |
7 | 7 | ||
8 | include scripts/Kbuild.include | 8 | include scripts/Kbuild.include |
@@ -12,7 +12,7 @@ include scripts/Kbuild.include | |||
12 | __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) | 12 | __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) |
13 | modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) | 13 | modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) |
14 | 14 | ||
15 | .PHONY: $(modules) | 15 | PHONY += $(modules) |
16 | __modinst: $(modules) | 16 | __modinst: $(modules) |
17 | @: | 17 | @: |
18 | 18 | ||
@@ -27,3 +27,9 @@ modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) | |||
27 | 27 | ||
28 | $(modules): | 28 | $(modules): |
29 | $(call cmd,modules_install,$(MODLIB)/$(modinst_dir)) | 29 | $(call cmd,modules_install,$(MODLIB)/$(modinst_dir)) |
30 | |||
31 | |||
32 | # Declare the contents of the .PHONY variable as phony. We keep that | ||
33 | # information in a variable se we can use it in if_changed and friends. | ||
34 | |||
35 | .PHONY: $(PHONY) | ||
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 9a3ec20b0be2..0e056cffffdb 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost | |||
@@ -32,14 +32,15 @@ | |||
32 | # Step 4 is solely used to allow module versioning in external modules, | 32 | # Step 4 is solely used to allow module versioning in external modules, |
33 | # where the CRC of each module is retrieved from the Module.symers file. | 33 | # where the CRC of each module is retrieved from the Module.symers file. |
34 | 34 | ||
35 | .PHONY: _modpost | 35 | PHONY := _modpost |
36 | _modpost: __modpost | 36 | _modpost: __modpost |
37 | 37 | ||
38 | include .config | 38 | include .config |
39 | include scripts/Kbuild.include | 39 | include scripts/Kbuild.include |
40 | include scripts/Makefile.lib | 40 | include scripts/Makefile.lib |
41 | 41 | ||
42 | symverfile := $(objtree)/Module.symvers | 42 | kernelsymfile := $(objtree)/Module.symvers |
43 | modulesymfile := $(KBUILD_EXTMOD)/Modules.symvers | ||
43 | 44 | ||
44 | # Step 1), find all modules listed in $(MODVERDIR)/ | 45 | # Step 1), find all modules listed in $(MODVERDIR)/ |
45 | __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) | 46 | __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) |
@@ -54,10 +55,12 @@ quiet_cmd_modpost = MODPOST | |||
54 | cmd_modpost = scripts/mod/modpost \ | 55 | cmd_modpost = scripts/mod/modpost \ |
55 | $(if $(CONFIG_MODVERSIONS),-m) \ | 56 | $(if $(CONFIG_MODVERSIONS),-m) \ |
56 | $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ | 57 | $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ |
57 | $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \ | 58 | $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ |
59 | $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ | ||
60 | $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ | ||
58 | $(filter-out FORCE,$^) | 61 | $(filter-out FORCE,$^) |
59 | 62 | ||
60 | .PHONY: __modpost | 63 | PHONY += __modpost |
61 | __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE | 64 | __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE |
62 | $(call cmd,modpost) | 65 | $(call cmd,modpost) |
63 | 66 | ||
@@ -94,7 +97,7 @@ targets += $(modules) | |||
94 | # Add FORCE to the prequisites of a target to force it to be always rebuilt. | 97 | # Add FORCE to the prequisites of a target to force it to be always rebuilt. |
95 | # --------------------------------------------------------------------------- | 98 | # --------------------------------------------------------------------------- |
96 | 99 | ||
97 | .PHONY: FORCE | 100 | PHONY += FORCE |
98 | 101 | ||
99 | FORCE: | 102 | FORCE: |
100 | 103 | ||
@@ -109,3 +112,9 @@ cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) | |||
109 | ifneq ($(cmd_files),) | 112 | ifneq ($(cmd_files),) |
110 | include $(cmd_files) | 113 | include $(cmd_files) |
111 | endif | 114 | endif |
115 | |||
116 | |||
117 | # Declare the contents of the .PHONY variable as phony. We keep that | ||
118 | # information in a variable se we can use it in if_changed and friends. | ||
119 | |||
120 | .PHONY: $(PHONY) | ||
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 679124b11e12..668a11a8b383 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c | |||
@@ -132,20 +132,10 @@ void usage(void) | |||
132 | 132 | ||
133 | /* | 133 | /* |
134 | * Print out the commandline prefixed with cmd_<target filename> := | 134 | * Print out the commandline prefixed with cmd_<target filename> := |
135 | * If commandline contains '#' escape with '\' so make to not see | 135 | */ |
136 | * the '#' as a start-of-comment symbol | ||
137 | **/ | ||
138 | void print_cmdline(void) | 136 | void print_cmdline(void) |
139 | { | 137 | { |
140 | char *p = cmdline; | 138 | printf("cmd_%s := %s\n\n", target, cmdline); |
141 | |||
142 | printf("cmd_%s := ", target); | ||
143 | for (; *p; p++) { | ||
144 | if (*p == '#') | ||
145 | printf("\\"); | ||
146 | printf("%c", *p); | ||
147 | } | ||
148 | printf("\n\n"); | ||
149 | } | 139 | } |
150 | 140 | ||
151 | char * str_config = NULL; | 141 | char * str_config = NULL; |
diff --git a/scripts/checkconfig.pl b/scripts/checkconfig.pl deleted file mode 100755 index ca1f231b15a6..000000000000 --- a/scripts/checkconfig.pl +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | #! /usr/bin/perl | ||
2 | # | ||
3 | # checkconfig: find uses of CONFIG_* names without matching definitions. | ||
4 | # Copyright abandoned, 1998, Michael Elizabeth Chastain <mailto:mec@shout.net>. | ||
5 | |||
6 | use integer; | ||
7 | |||
8 | $| = 1; | ||
9 | |||
10 | foreach $file (@ARGV) | ||
11 | { | ||
12 | # Open this file. | ||
13 | open(FILE, $file) || die "Can't open $file: $!\n"; | ||
14 | |||
15 | # Initialize variables. | ||
16 | my $fInComment = 0; | ||
17 | my $fInString = 0; | ||
18 | my $fUseConfig = 0; | ||
19 | my $iLinuxConfig = 0; | ||
20 | my %configList = (); | ||
21 | |||
22 | LINE: while ( <FILE> ) | ||
23 | { | ||
24 | # Strip comments. | ||
25 | $fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next); | ||
26 | m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1))); | ||
27 | |||
28 | # Pick up definitions. | ||
29 | if ( m/^\s*#/o ) | ||
30 | { | ||
31 | $iLinuxConfig = $. if m/^\s*#\s*include\s*"linux\/config\.h"/o; | ||
32 | $configList{uc $1} = 1 if m/^\s*#\s*include\s*"config\/(\S*)\.h"/o; | ||
33 | } | ||
34 | |||
35 | # Strip strings. | ||
36 | $fInString && (s+^.*?"+ +o ? ($fInString = 0) : next); | ||
37 | m+"+o && (s+".*?"+ +go, (s+".*$+ +o && ($fInString = 1))); | ||
38 | |||
39 | # Pick up definitions. | ||
40 | if ( m/^\s*#/o ) | ||
41 | { | ||
42 | $iLinuxConfig = $. if m/^\s*#\s*include\s*<linux\/config\.h>/o; | ||
43 | $configList{uc $1} = 1 if m/^\s*#\s*include\s*<config\/(\S*)\.h>/o; | ||
44 | $configList{$1} = 1 if m/^\s*#\s*define\s+CONFIG_(\w*)/o; | ||
45 | $configList{$1} = 1 if m/^\s*#\s*undef\s+CONFIG_(\w*)/o; | ||
46 | } | ||
47 | |||
48 | # Look for usages. | ||
49 | next unless m/CONFIG_/o; | ||
50 | WORD: while ( m/\bCONFIG_(\w+)/og ) | ||
51 | { | ||
52 | $fUseConfig = 1; | ||
53 | last LINE if $iLinuxConfig; | ||
54 | next WORD if exists $configList{$1}; | ||
55 | print "$file: $.: need CONFIG_$1.\n"; | ||
56 | $configList{$1} = 0; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | # Report superfluous includes. | ||
61 | if ( $iLinuxConfig && ! $fUseConfig ) | ||
62 | { print "$file: $iLinuxConfig: linux/config.h not needed.\n"; } | ||
63 | |||
64 | close(FILE); | ||
65 | } | ||
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 416a694b0998..5b0344e20d61 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c | |||
@@ -29,481 +29,421 @@ | |||
29 | #include <stdarg.h> | 29 | #include <stdarg.h> |
30 | #ifdef __GNU_LIBRARY__ | 30 | #ifdef __GNU_LIBRARY__ |
31 | #include <getopt.h> | 31 | #include <getopt.h> |
32 | #endif /* __GNU_LIBRARY__ */ | 32 | #endif /* __GNU_LIBRARY__ */ |
33 | 33 | ||
34 | #include "genksyms.h" | 34 | #include "genksyms.h" |
35 | |||
36 | /*----------------------------------------------------------------------*/ | 35 | /*----------------------------------------------------------------------*/ |
37 | 36 | ||
38 | #define HASH_BUCKETS 4096 | 37 | #define HASH_BUCKETS 4096 |
39 | 38 | ||
40 | static struct symbol *symtab[HASH_BUCKETS]; | 39 | static struct symbol *symtab[HASH_BUCKETS]; |
41 | FILE *debugfile; | 40 | static FILE *debugfile; |
42 | 41 | ||
43 | int cur_line = 1; | 42 | int cur_line = 1; |
44 | char *cur_filename, *output_directory; | 43 | char *cur_filename; |
45 | 44 | ||
46 | int flag_debug, flag_dump_defs, flag_warnings; | 45 | static int flag_debug, flag_dump_defs, flag_warnings; |
46 | static const char *arch = ""; | ||
47 | static const char *mod_prefix = ""; | ||
47 | 48 | ||
48 | static int errors; | 49 | static int errors; |
49 | static int nsyms; | 50 | static int nsyms; |
50 | 51 | ||
51 | static struct symbol *expansion_trail; | 52 | static struct symbol *expansion_trail; |
52 | 53 | ||
53 | static const char * const symbol_type_name[] = { | 54 | static const char *const symbol_type_name[] = { |
54 | "normal", "typedef", "enum", "struct", "union" | 55 | "normal", "typedef", "enum", "struct", "union" |
55 | }; | 56 | }; |
56 | 57 | ||
58 | static int equal_list(struct string_list *a, struct string_list *b); | ||
59 | static void print_list(FILE * f, struct string_list *list); | ||
60 | |||
57 | /*----------------------------------------------------------------------*/ | 61 | /*----------------------------------------------------------------------*/ |
58 | 62 | ||
59 | static const unsigned int crctab32[] = | 63 | static const unsigned int crctab32[] = { |
60 | { | 64 | 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, |
61 | 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, | 65 | 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, |
62 | 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, | 66 | 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, |
63 | 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, | 67 | 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, |
64 | 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, | 68 | 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, |
65 | 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, | 69 | 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, |
66 | 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, | 70 | 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, |
67 | 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, | 71 | 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, |
68 | 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, | 72 | 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, |
69 | 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, | 73 | 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, |
70 | 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, | 74 | 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, |
71 | 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, | 75 | 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, |
72 | 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, | 76 | 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, |
73 | 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, | 77 | 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, |
74 | 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, | 78 | 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, |
75 | 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, | 79 | 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, |
76 | 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, | 80 | 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, |
77 | 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, | 81 | 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, |
78 | 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, | 82 | 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, |
79 | 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, | 83 | 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, |
80 | 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, | 84 | 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, |
81 | 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, | 85 | 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, |
82 | 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, | 86 | 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, |
83 | 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, | 87 | 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, |
84 | 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, | 88 | 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, |
85 | 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, | 89 | 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, |
86 | 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, | 90 | 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, |
87 | 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, | 91 | 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, |
88 | 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, | 92 | 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, |
89 | 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, | 93 | 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, |
90 | 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, | 94 | 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, |
91 | 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, | 95 | 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, |
92 | 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, | 96 | 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, |
93 | 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, | 97 | 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, |
94 | 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, | 98 | 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, |
95 | 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, | 99 | 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, |
96 | 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, | 100 | 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, |
97 | 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, | 101 | 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, |
98 | 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, | 102 | 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, |
99 | 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, | 103 | 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, |
100 | 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, | 104 | 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, |
101 | 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, | 105 | 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, |
102 | 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, | 106 | 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, |
103 | 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, | 107 | 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, |
104 | 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, | 108 | 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, |
105 | 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, | 109 | 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, |
106 | 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, | 110 | 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, |
107 | 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, | 111 | 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, |
108 | 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, | 112 | 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, |
109 | 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, | 113 | 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, |
110 | 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, | 114 | 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, |
111 | 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, | 115 | 0x2d02ef8dU |
112 | 0x2d02ef8dU | ||
113 | }; | 116 | }; |
114 | 117 | ||
115 | static inline unsigned long | 118 | static unsigned long partial_crc32_one(unsigned char c, unsigned long crc) |
116 | partial_crc32_one(unsigned char c, unsigned long crc) | ||
117 | { | 119 | { |
118 | return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); | 120 | return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); |
119 | } | 121 | } |
120 | 122 | ||
121 | static inline unsigned long | 123 | static unsigned long partial_crc32(const char *s, unsigned long crc) |
122 | partial_crc32(const char *s, unsigned long crc) | ||
123 | { | 124 | { |
124 | while (*s) | 125 | while (*s) |
125 | crc = partial_crc32_one(*s++, crc); | 126 | crc = partial_crc32_one(*s++, crc); |
126 | return crc; | 127 | return crc; |
127 | } | 128 | } |
128 | 129 | ||
129 | static inline unsigned long | 130 | static unsigned long crc32(const char *s) |
130 | crc32(const char *s) | ||
131 | { | 131 | { |
132 | return partial_crc32(s, 0xffffffff) ^ 0xffffffff; | 132 | return partial_crc32(s, 0xffffffff) ^ 0xffffffff; |
133 | } | 133 | } |
134 | 134 | ||
135 | |||
136 | /*----------------------------------------------------------------------*/ | 135 | /*----------------------------------------------------------------------*/ |
137 | 136 | ||
138 | static inline enum symbol_type | 137 | static enum symbol_type map_to_ns(enum symbol_type t) |
139 | map_to_ns(enum symbol_type t) | ||
140 | { | 138 | { |
141 | if (t == SYM_TYPEDEF) | 139 | if (t == SYM_TYPEDEF) |
142 | t = SYM_NORMAL; | 140 | t = SYM_NORMAL; |
143 | else if (t == SYM_UNION) | 141 | else if (t == SYM_UNION) |
144 | t = SYM_STRUCT; | 142 | t = SYM_STRUCT; |
145 | return t; | 143 | return t; |
146 | } | 144 | } |
147 | 145 | ||
148 | struct symbol * | 146 | struct symbol *find_symbol(const char *name, enum symbol_type ns) |
149 | find_symbol(const char *name, enum symbol_type ns) | ||
150 | { | 147 | { |
151 | unsigned long h = crc32(name) % HASH_BUCKETS; | 148 | unsigned long h = crc32(name) % HASH_BUCKETS; |
152 | struct symbol *sym; | 149 | struct symbol *sym; |
153 | 150 | ||
154 | for (sym = symtab[h]; sym ; sym = sym->hash_next) | 151 | for (sym = symtab[h]; sym; sym = sym->hash_next) |
155 | if (map_to_ns(sym->type) == map_to_ns(ns) && strcmp(name, sym->name) == 0) | 152 | if (map_to_ns(sym->type) == map_to_ns(ns) && |
156 | break; | 153 | strcmp(name, sym->name) == 0) |
154 | break; | ||
157 | 155 | ||
158 | return sym; | 156 | return sym; |
159 | } | 157 | } |
160 | 158 | ||
161 | struct symbol * | 159 | struct symbol *add_symbol(const char *name, enum symbol_type type, |
162 | add_symbol(const char *name, enum symbol_type type, struct string_list *defn, int is_extern) | 160 | struct string_list *defn, int is_extern) |
163 | { | 161 | { |
164 | unsigned long h = crc32(name) % HASH_BUCKETS; | 162 | unsigned long h = crc32(name) % HASH_BUCKETS; |
165 | struct symbol *sym; | 163 | struct symbol *sym; |
166 | 164 | ||
167 | for (sym = symtab[h]; sym ; sym = sym->hash_next) | 165 | for (sym = symtab[h]; sym; sym = sym->hash_next) { |
168 | if (map_to_ns(sym->type) == map_to_ns(type) | 166 | if (map_to_ns(sym->type) == map_to_ns(type) |
169 | && strcmp(name, sym->name) == 0) | 167 | && strcmp(name, sym->name) == 0) { |
170 | { | 168 | if (!equal_list(sym->defn, defn)) |
171 | if (!equal_list(sym->defn, defn)) | 169 | error_with_pos("redefinition of %s", name); |
172 | error_with_pos("redefinition of %s", name); | 170 | return sym; |
171 | } | ||
172 | } | ||
173 | |||
174 | sym = xmalloc(sizeof(*sym)); | ||
175 | sym->name = name; | ||
176 | sym->type = type; | ||
177 | sym->defn = defn; | ||
178 | sym->expansion_trail = NULL; | ||
179 | sym->is_extern = is_extern; | ||
180 | |||
181 | sym->hash_next = symtab[h]; | ||
182 | symtab[h] = sym; | ||
183 | |||
184 | if (flag_debug) { | ||
185 | fprintf(debugfile, "Defn for %s %s == <", | ||
186 | symbol_type_name[type], name); | ||
187 | if (is_extern) | ||
188 | fputs("extern ", debugfile); | ||
189 | print_list(debugfile, defn); | ||
190 | fputs(">\n", debugfile); | ||
191 | } | ||
192 | |||
193 | ++nsyms; | ||
173 | return sym; | 194 | return sym; |
174 | } | ||
175 | |||
176 | sym = xmalloc(sizeof(*sym)); | ||
177 | sym->name = name; | ||
178 | sym->type = type; | ||
179 | sym->defn = defn; | ||
180 | sym->expansion_trail = NULL; | ||
181 | sym->is_extern = is_extern; | ||
182 | |||
183 | sym->hash_next = symtab[h]; | ||
184 | symtab[h] = sym; | ||
185 | |||
186 | if (flag_debug) | ||
187 | { | ||
188 | fprintf(debugfile, "Defn for %s %s == <", symbol_type_name[type], name); | ||
189 | if (is_extern) | ||
190 | fputs("extern ", debugfile); | ||
191 | print_list(debugfile, defn); | ||
192 | fputs(">\n", debugfile); | ||
193 | } | ||
194 | |||
195 | ++nsyms; | ||
196 | return sym; | ||
197 | } | 195 | } |
198 | 196 | ||
199 | |||
200 | /*----------------------------------------------------------------------*/ | 197 | /*----------------------------------------------------------------------*/ |
201 | 198 | ||
202 | inline void | 199 | void free_node(struct string_list *node) |
203 | free_node(struct string_list *node) | ||
204 | { | 200 | { |
205 | free(node->string); | 201 | free(node->string); |
206 | free(node); | 202 | free(node); |
207 | } | 203 | } |
208 | 204 | ||
209 | void | 205 | void free_list(struct string_list *s, struct string_list *e) |
210 | free_list(struct string_list *s, struct string_list *e) | ||
211 | { | 206 | { |
212 | while (s != e) | 207 | while (s != e) { |
213 | { | 208 | struct string_list *next = s->next; |
214 | struct string_list *next = s->next; | 209 | free_node(s); |
215 | free_node(s); | 210 | s = next; |
216 | s = next; | 211 | } |
217 | } | ||
218 | } | 212 | } |
219 | 213 | ||
220 | inline struct string_list * | 214 | struct string_list *copy_node(struct string_list *node) |
221 | copy_node(struct string_list *node) | ||
222 | { | 215 | { |
223 | struct string_list *newnode; | 216 | struct string_list *newnode; |
224 | 217 | ||
225 | newnode = xmalloc(sizeof(*newnode)); | 218 | newnode = xmalloc(sizeof(*newnode)); |
226 | newnode->string = xstrdup(node->string); | 219 | newnode->string = xstrdup(node->string); |
227 | newnode->tag = node->tag; | 220 | newnode->tag = node->tag; |
228 | 221 | ||
229 | return newnode; | 222 | return newnode; |
230 | } | 223 | } |
231 | 224 | ||
232 | struct string_list * | 225 | static int equal_list(struct string_list *a, struct string_list *b) |
233 | copy_list(struct string_list *s, struct string_list *e) | ||
234 | { | 226 | { |
235 | struct string_list *h, *p; | 227 | while (a && b) { |
236 | 228 | if (a->tag != b->tag || strcmp(a->string, b->string)) | |
237 | if (s == e) | 229 | return 0; |
238 | return NULL; | 230 | a = a->next; |
239 | 231 | b = b->next; | |
240 | p = h = copy_node(s); | 232 | } |
241 | while ((s = s->next) != e) | ||
242 | p = p->next = copy_node(s); | ||
243 | p->next = NULL; | ||
244 | |||
245 | return h; | ||
246 | } | ||
247 | 233 | ||
248 | int | 234 | return !a && !b; |
249 | equal_list(struct string_list *a, struct string_list *b) | ||
250 | { | ||
251 | while (a && b) | ||
252 | { | ||
253 | if (a->tag != b->tag || strcmp(a->string, b->string)) | ||
254 | return 0; | ||
255 | a = a->next; | ||
256 | b = b->next; | ||
257 | } | ||
258 | |||
259 | return !a && !b; | ||
260 | } | 235 | } |
261 | 236 | ||
262 | static inline void | 237 | static void print_node(FILE * f, struct string_list *list) |
263 | print_node(FILE *f, struct string_list *list) | ||
264 | { | 238 | { |
265 | switch (list->tag) | 239 | switch (list->tag) { |
266 | { | 240 | case SYM_STRUCT: |
267 | case SYM_STRUCT: | 241 | putc('s', f); |
268 | putc('s', f); | 242 | goto printit; |
269 | goto printit; | 243 | case SYM_UNION: |
270 | case SYM_UNION: | 244 | putc('u', f); |
271 | putc('u', f); | 245 | goto printit; |
272 | goto printit; | 246 | case SYM_ENUM: |
273 | case SYM_ENUM: | 247 | putc('e', f); |
274 | putc('e', f); | 248 | goto printit; |
275 | goto printit; | 249 | case SYM_TYPEDEF: |
276 | case SYM_TYPEDEF: | 250 | putc('t', f); |
277 | putc('t', f); | 251 | goto printit; |
278 | goto printit; | ||
279 | |||
280 | printit: | ||
281 | putc('#', f); | ||
282 | case SYM_NORMAL: | ||
283 | fputs(list->string, f); | ||
284 | break; | ||
285 | } | ||
286 | } | ||
287 | 252 | ||
288 | void | 253 | printit: |
289 | print_list(FILE *f, struct string_list *list) | 254 | putc('#', f); |
290 | { | 255 | case SYM_NORMAL: |
291 | struct string_list **e, **b; | 256 | fputs(list->string, f); |
292 | struct string_list *tmp, **tmp2; | 257 | break; |
293 | int elem = 1; | 258 | } |
294 | |||
295 | if (list == NULL) | ||
296 | { | ||
297 | fputs("(nil)", f); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | tmp = list; | ||
302 | while((tmp = tmp->next) != NULL) | ||
303 | elem++; | ||
304 | |||
305 | b = alloca(elem * sizeof(*e)); | ||
306 | e = b + elem; | ||
307 | tmp2 = e - 1; | ||
308 | |||
309 | (*tmp2--) = list; | ||
310 | while((list = list->next) != NULL) | ||
311 | *(tmp2--) = list; | ||
312 | |||
313 | while (b != e) | ||
314 | { | ||
315 | print_node(f, *b++); | ||
316 | putc(' ', f); | ||
317 | } | ||
318 | } | 259 | } |
319 | 260 | ||
320 | static unsigned long | 261 | static void print_list(FILE * f, struct string_list *list) |
321 | expand_and_crc_list(struct string_list *list, unsigned long crc) | ||
322 | { | 262 | { |
323 | struct string_list **e, **b; | 263 | struct string_list **e, **b; |
324 | struct string_list *tmp, **tmp2; | 264 | struct string_list *tmp, **tmp2; |
325 | int elem = 1; | 265 | int elem = 1; |
326 | |||
327 | if (!list) | ||
328 | return crc; | ||
329 | 266 | ||
330 | tmp = list; | 267 | if (list == NULL) { |
331 | while((tmp = tmp->next) != NULL) | 268 | fputs("(nil)", f); |
332 | elem++; | 269 | return; |
333 | 270 | } | |
334 | b = alloca(elem * sizeof(*e)); | ||
335 | e = b + elem; | ||
336 | tmp2 = e - 1; | ||
337 | 271 | ||
338 | *(tmp2--) = list; | 272 | tmp = list; |
339 | while ((list = list->next) != NULL) | 273 | while ((tmp = tmp->next) != NULL) |
340 | *(tmp2--) = list; | 274 | elem++; |
341 | 275 | ||
342 | while (b != e) | 276 | b = alloca(elem * sizeof(*e)); |
343 | { | 277 | e = b + elem; |
344 | struct string_list *cur; | 278 | tmp2 = e - 1; |
345 | struct symbol *subsym; | ||
346 | 279 | ||
347 | cur = *(b++); | 280 | (*tmp2--) = list; |
348 | switch (cur->tag) | 281 | while ((list = list->next) != NULL) |
349 | { | 282 | *(tmp2--) = list; |
350 | case SYM_NORMAL: | ||
351 | if (flag_dump_defs) | ||
352 | fprintf(debugfile, "%s ", cur->string); | ||
353 | crc = partial_crc32(cur->string, crc); | ||
354 | crc = partial_crc32_one(' ', crc); | ||
355 | break; | ||
356 | 283 | ||
357 | case SYM_TYPEDEF: | 284 | while (b != e) { |
358 | subsym = find_symbol(cur->string, cur->tag); | 285 | print_node(f, *b++); |
359 | if (subsym->expansion_trail) | 286 | putc(' ', f); |
360 | { | 287 | } |
361 | if (flag_dump_defs) | 288 | } |
362 | fprintf(debugfile, "%s ", cur->string); | ||
363 | crc = partial_crc32(cur->string, crc); | ||
364 | crc = partial_crc32_one(' ', crc); | ||
365 | } | ||
366 | else | ||
367 | { | ||
368 | subsym->expansion_trail = expansion_trail; | ||
369 | expansion_trail = subsym; | ||
370 | crc = expand_and_crc_list(subsym->defn, crc); | ||
371 | } | ||
372 | break; | ||
373 | 289 | ||
374 | case SYM_STRUCT: | 290 | static unsigned long expand_and_crc_list(struct string_list *list, |
375 | case SYM_UNION: | 291 | unsigned long crc) |
376 | case SYM_ENUM: | 292 | { |
377 | subsym = find_symbol(cur->string, cur->tag); | 293 | struct string_list **e, **b; |
378 | if (!subsym) | 294 | struct string_list *tmp, **tmp2; |
379 | { | 295 | int elem = 1; |
380 | struct string_list *n, *t = NULL; | 296 | |
381 | 297 | if (!list) | |
382 | error_with_pos("expand undefined %s %s", | 298 | return crc; |
383 | symbol_type_name[cur->tag], cur->string); | 299 | |
384 | 300 | tmp = list; | |
385 | n = xmalloc(sizeof(*n)); | 301 | while ((tmp = tmp->next) != NULL) |
386 | n->string = xstrdup(symbol_type_name[cur->tag]); | 302 | elem++; |
387 | n->tag = SYM_NORMAL; | 303 | |
388 | n->next = t; | 304 | b = alloca(elem * sizeof(*e)); |
389 | t = n; | 305 | e = b + elem; |
390 | 306 | tmp2 = e - 1; | |
391 | n = xmalloc(sizeof(*n)); | 307 | |
392 | n->string = xstrdup(cur->string); | 308 | *(tmp2--) = list; |
393 | n->tag = SYM_NORMAL; | 309 | while ((list = list->next) != NULL) |
394 | n->next = t; | 310 | *(tmp2--) = list; |
395 | t = n; | 311 | |
396 | 312 | while (b != e) { | |
397 | n = xmalloc(sizeof(*n)); | 313 | struct string_list *cur; |
398 | n->string = xstrdup("{ UNKNOWN }"); | 314 | struct symbol *subsym; |
399 | n->tag = SYM_NORMAL; | 315 | |
400 | n->next = t; | 316 | cur = *(b++); |
401 | 317 | switch (cur->tag) { | |
402 | subsym = add_symbol(cur->string, cur->tag, n, 0); | 318 | case SYM_NORMAL: |
403 | } | 319 | if (flag_dump_defs) |
404 | if (subsym->expansion_trail) | 320 | fprintf(debugfile, "%s ", cur->string); |
405 | { | 321 | crc = partial_crc32(cur->string, crc); |
406 | if (flag_dump_defs) | 322 | crc = partial_crc32_one(' ', crc); |
407 | { | 323 | break; |
408 | fprintf(debugfile, "%s %s ", symbol_type_name[cur->tag], | 324 | |
409 | cur->string); | 325 | case SYM_TYPEDEF: |
326 | subsym = find_symbol(cur->string, cur->tag); | ||
327 | if (subsym->expansion_trail) { | ||
328 | if (flag_dump_defs) | ||
329 | fprintf(debugfile, "%s ", cur->string); | ||
330 | crc = partial_crc32(cur->string, crc); | ||
331 | crc = partial_crc32_one(' ', crc); | ||
332 | } else { | ||
333 | subsym->expansion_trail = expansion_trail; | ||
334 | expansion_trail = subsym; | ||
335 | crc = expand_and_crc_list(subsym->defn, crc); | ||
336 | } | ||
337 | break; | ||
338 | |||
339 | case SYM_STRUCT: | ||
340 | case SYM_UNION: | ||
341 | case SYM_ENUM: | ||
342 | subsym = find_symbol(cur->string, cur->tag); | ||
343 | if (!subsym) { | ||
344 | struct string_list *n, *t = NULL; | ||
345 | |||
346 | error_with_pos("expand undefined %s %s", | ||
347 | symbol_type_name[cur->tag], | ||
348 | cur->string); | ||
349 | |||
350 | n = xmalloc(sizeof(*n)); | ||
351 | n->string = xstrdup(symbol_type_name[cur->tag]); | ||
352 | n->tag = SYM_NORMAL; | ||
353 | n->next = t; | ||
354 | t = n; | ||
355 | |||
356 | n = xmalloc(sizeof(*n)); | ||
357 | n->string = xstrdup(cur->string); | ||
358 | n->tag = SYM_NORMAL; | ||
359 | n->next = t; | ||
360 | t = n; | ||
361 | |||
362 | n = xmalloc(sizeof(*n)); | ||
363 | n->string = xstrdup("{ UNKNOWN }"); | ||
364 | n->tag = SYM_NORMAL; | ||
365 | n->next = t; | ||
366 | |||
367 | subsym = | ||
368 | add_symbol(cur->string, cur->tag, n, 0); | ||
369 | } | ||
370 | if (subsym->expansion_trail) { | ||
371 | if (flag_dump_defs) { | ||
372 | fprintf(debugfile, "%s %s ", | ||
373 | symbol_type_name[cur->tag], | ||
374 | cur->string); | ||
375 | } | ||
376 | |||
377 | crc = partial_crc32(symbol_type_name[cur->tag], | ||
378 | crc); | ||
379 | crc = partial_crc32_one(' ', crc); | ||
380 | crc = partial_crc32(cur->string, crc); | ||
381 | crc = partial_crc32_one(' ', crc); | ||
382 | } else { | ||
383 | subsym->expansion_trail = expansion_trail; | ||
384 | expansion_trail = subsym; | ||
385 | crc = expand_and_crc_list(subsym->defn, crc); | ||
386 | } | ||
387 | break; | ||
410 | } | 388 | } |
411 | |||
412 | crc = partial_crc32(symbol_type_name[cur->tag], crc); | ||
413 | crc = partial_crc32_one(' ', crc); | ||
414 | crc = partial_crc32(cur->string, crc); | ||
415 | crc = partial_crc32_one(' ', crc); | ||
416 | } | ||
417 | else | ||
418 | { | ||
419 | subsym->expansion_trail = expansion_trail; | ||
420 | expansion_trail = subsym; | ||
421 | crc = expand_and_crc_list(subsym->defn, crc); | ||
422 | } | ||
423 | break; | ||
424 | } | 389 | } |
425 | } | ||
426 | 390 | ||
427 | return crc; | 391 | return crc; |
428 | } | 392 | } |
429 | 393 | ||
430 | void | 394 | void export_symbol(const char *name) |
431 | export_symbol(const char *name) | ||
432 | { | 395 | { |
433 | struct symbol *sym; | 396 | struct symbol *sym; |
434 | 397 | ||
435 | sym = find_symbol(name, SYM_NORMAL); | 398 | sym = find_symbol(name, SYM_NORMAL); |
436 | if (!sym) | 399 | if (!sym) |
437 | error_with_pos("export undefined symbol %s", name); | 400 | error_with_pos("export undefined symbol %s", name); |
438 | else | 401 | else { |
439 | { | 402 | unsigned long crc; |
440 | unsigned long crc; | ||
441 | 403 | ||
442 | if (flag_dump_defs) | 404 | if (flag_dump_defs) |
443 | fprintf(debugfile, "Export %s == <", name); | 405 | fprintf(debugfile, "Export %s == <", name); |
444 | 406 | ||
445 | expansion_trail = (struct symbol *)-1L; | 407 | expansion_trail = (struct symbol *)-1L; |
446 | 408 | ||
447 | crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff; | 409 | crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff; |
448 | 410 | ||
449 | sym = expansion_trail; | 411 | sym = expansion_trail; |
450 | while (sym != (struct symbol *)-1L) | 412 | while (sym != (struct symbol *)-1L) { |
451 | { | 413 | struct symbol *n = sym->expansion_trail; |
452 | struct symbol *n = sym->expansion_trail; | 414 | sym->expansion_trail = 0; |
453 | sym->expansion_trail = 0; | 415 | sym = n; |
454 | sym = n; | 416 | } |
455 | } | ||
456 | 417 | ||
457 | if (flag_dump_defs) | 418 | if (flag_dump_defs) |
458 | fputs(">\n", debugfile); | 419 | fputs(">\n", debugfile); |
459 | 420 | ||
460 | /* Used as a linker script. */ | 421 | /* Used as a linker script. */ |
461 | printf("__crc_%s = 0x%08lx ;\n", name, crc); | 422 | printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc); |
462 | } | 423 | } |
463 | } | 424 | } |
464 | 425 | ||
465 | /*----------------------------------------------------------------------*/ | 426 | /*----------------------------------------------------------------------*/ |
466 | 427 | void error_with_pos(const char *fmt, ...) | |
467 | void | ||
468 | error(const char *fmt, ...) | ||
469 | { | ||
470 | va_list args; | ||
471 | |||
472 | if (flag_warnings) | ||
473 | { | ||
474 | va_start(args, fmt); | ||
475 | vfprintf(stderr, fmt, args); | ||
476 | va_end(args); | ||
477 | putc('\n', stderr); | ||
478 | |||
479 | errors++; | ||
480 | } | ||
481 | } | ||
482 | |||
483 | void | ||
484 | error_with_pos(const char *fmt, ...) | ||
485 | { | 428 | { |
486 | va_list args; | 429 | va_list args; |
487 | 430 | ||
488 | if (flag_warnings) | 431 | if (flag_warnings) { |
489 | { | 432 | fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", |
490 | fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line); | 433 | cur_line); |
491 | 434 | ||
492 | va_start(args, fmt); | 435 | va_start(args, fmt); |
493 | vfprintf(stderr, fmt, args); | 436 | vfprintf(stderr, fmt, args); |
494 | va_end(args); | 437 | va_end(args); |
495 | putc('\n', stderr); | 438 | putc('\n', stderr); |
496 | 439 | ||
497 | errors++; | 440 | errors++; |
498 | } | 441 | } |
499 | } | 442 | } |
500 | 443 | ||
501 | 444 | static void genksyms_usage(void) | |
502 | void genksyms_usage(void) | ||
503 | { | 445 | { |
504 | fputs("Usage:\n" | 446 | fputs("Usage:\n" "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" "\n" |
505 | "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" | ||
506 | "\n" | ||
507 | #ifdef __GNU_LIBRARY__ | 447 | #ifdef __GNU_LIBRARY__ |
508 | " -d, --debug Increment the debug level (repeatable)\n" | 448 | " -d, --debug Increment the debug level (repeatable)\n" |
509 | " -D, --dump Dump expanded symbol defs (for debugging only)\n" | 449 | " -D, --dump Dump expanded symbol defs (for debugging only)\n" |
@@ -511,81 +451,84 @@ void genksyms_usage(void) | |||
511 | " -q, --quiet Disable warnings (default)\n" | 451 | " -q, --quiet Disable warnings (default)\n" |
512 | " -h, --help Print this message\n" | 452 | " -h, --help Print this message\n" |
513 | " -V, --version Print the release version\n" | 453 | " -V, --version Print the release version\n" |
514 | #else /* __GNU_LIBRARY__ */ | 454 | #else /* __GNU_LIBRARY__ */ |
515 | " -d Increment the debug level (repeatable)\n" | 455 | " -d Increment the debug level (repeatable)\n" |
516 | " -D Dump expanded symbol defs (for debugging only)\n" | 456 | " -D Dump expanded symbol defs (for debugging only)\n" |
517 | " -w Enable warnings\n" | 457 | " -w Enable warnings\n" |
518 | " -q Disable warnings (default)\n" | 458 | " -q Disable warnings (default)\n" |
519 | " -h Print this message\n" | 459 | " -h Print this message\n" |
520 | " -V Print the release version\n" | 460 | " -V Print the release version\n" |
521 | #endif /* __GNU_LIBRARY__ */ | 461 | #endif /* __GNU_LIBRARY__ */ |
522 | , stderr); | 462 | , stderr); |
523 | } | 463 | } |
524 | 464 | ||
525 | int | 465 | int main(int argc, char **argv) |
526 | main(int argc, char **argv) | ||
527 | { | 466 | { |
528 | int o; | 467 | int o; |
529 | 468 | ||
530 | #ifdef __GNU_LIBRARY__ | 469 | #ifdef __GNU_LIBRARY__ |
531 | struct option long_opts[] = { | 470 | struct option long_opts[] = { |
532 | {"debug", 0, 0, 'd'}, | 471 | {"arch", 1, 0, 'a'}, |
533 | {"warnings", 0, 0, 'w'}, | 472 | {"debug", 0, 0, 'd'}, |
534 | {"quiet", 0, 0, 'q'}, | 473 | {"warnings", 0, 0, 'w'}, |
535 | {"dump", 0, 0, 'D'}, | 474 | {"quiet", 0, 0, 'q'}, |
536 | {"version", 0, 0, 'V'}, | 475 | {"dump", 0, 0, 'D'}, |
537 | {"help", 0, 0, 'h'}, | 476 | {"version", 0, 0, 'V'}, |
538 | {0, 0, 0, 0} | 477 | {"help", 0, 0, 'h'}, |
539 | }; | 478 | {0, 0, 0, 0} |
540 | 479 | }; | |
541 | while ((o = getopt_long(argc, argv, "dwqVDk:p:", | 480 | |
542 | &long_opts[0], NULL)) != EOF) | 481 | while ((o = getopt_long(argc, argv, "a:dwqVDk:p:", |
543 | #else /* __GNU_LIBRARY__ */ | 482 | &long_opts[0], NULL)) != EOF) |
544 | while ((o = getopt(argc, argv, "dwqVDk:p:")) != EOF) | 483 | #else /* __GNU_LIBRARY__ */ |
545 | #endif /* __GNU_LIBRARY__ */ | 484 | while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF) |
546 | switch (o) | 485 | #endif /* __GNU_LIBRARY__ */ |
547 | { | 486 | switch (o) { |
548 | case 'd': | 487 | case 'a': |
549 | flag_debug++; | 488 | arch = optarg; |
550 | break; | 489 | break; |
551 | case 'w': | 490 | case 'd': |
552 | flag_warnings = 1; | 491 | flag_debug++; |
553 | break; | 492 | break; |
554 | case 'q': | 493 | case 'w': |
555 | flag_warnings = 0; | 494 | flag_warnings = 1; |
556 | break; | 495 | break; |
557 | case 'V': | 496 | case 'q': |
558 | fputs("genksyms version 2.5.60\n", stderr); | 497 | flag_warnings = 0; |
559 | break; | 498 | break; |
560 | case 'D': | 499 | case 'V': |
561 | flag_dump_defs = 1; | 500 | fputs("genksyms version 2.5.60\n", stderr); |
562 | break; | 501 | break; |
563 | case 'h': | 502 | case 'D': |
564 | genksyms_usage(); | 503 | flag_dump_defs = 1; |
565 | return 0; | 504 | break; |
566 | default: | 505 | case 'h': |
567 | genksyms_usage(); | 506 | genksyms_usage(); |
568 | return 1; | 507 | return 0; |
569 | } | 508 | default: |
570 | 509 | genksyms_usage(); | |
571 | { | 510 | return 1; |
572 | extern int yydebug; | 511 | } |
573 | extern int yy_flex_debug; | 512 | if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0)) |
574 | 513 | mod_prefix = "_"; | |
575 | yydebug = (flag_debug > 1); | 514 | { |
576 | yy_flex_debug = (flag_debug > 2); | 515 | extern int yydebug; |
577 | 516 | extern int yy_flex_debug; | |
578 | debugfile = stderr; | 517 | |
579 | /* setlinebuf(debugfile); */ | 518 | yydebug = (flag_debug > 1); |
580 | } | 519 | yy_flex_debug = (flag_debug > 2); |
581 | 520 | ||
582 | yyparse(); | 521 | debugfile = stderr; |
583 | 522 | /* setlinebuf(debugfile); */ | |
584 | if (flag_debug) | 523 | } |
585 | { | 524 | |
586 | fprintf(debugfile, "Hash table occupancy %d/%d = %g\n", | 525 | yyparse(); |
587 | nsyms, HASH_BUCKETS, (double)nsyms / (double)HASH_BUCKETS); | 526 | |
588 | } | 527 | if (flag_debug) { |
589 | 528 | fprintf(debugfile, "Hash table occupancy %d/%d = %g\n", | |
590 | return errors != 0; | 529 | nsyms, HASH_BUCKETS, |
530 | (double)nsyms / (double)HASH_BUCKETS); | ||
531 | } | ||
532 | |||
533 | return errors != 0; | ||
591 | } | 534 | } |
diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h index f09af47ab281..ab6f34f38735 100644 --- a/scripts/genksyms/genksyms.h +++ b/scripts/genksyms/genksyms.h | |||
@@ -20,74 +20,51 @@ | |||
20 | along with this program; if not, write to the Free Software Foundation, | 20 | along with this program; if not, write to the Free Software Foundation, |
21 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 21 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
22 | 22 | ||
23 | |||
24 | #ifndef MODUTILS_GENKSYMS_H | 23 | #ifndef MODUTILS_GENKSYMS_H |
25 | #define MODUTILS_GENKSYMS_H 1 | 24 | #define MODUTILS_GENKSYMS_H 1 |
26 | 25 | ||
27 | #include <stdio.h> | 26 | #include <stdio.h> |
28 | 27 | ||
29 | 28 | enum symbol_type { | |
30 | enum symbol_type | 29 | SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION |
31 | { | ||
32 | SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION | ||
33 | }; | 30 | }; |
34 | 31 | ||
35 | struct string_list | 32 | struct string_list { |
36 | { | 33 | struct string_list *next; |
37 | struct string_list *next; | 34 | enum symbol_type tag; |
38 | enum symbol_type tag; | 35 | char *string; |
39 | char *string; | ||
40 | }; | 36 | }; |
41 | 37 | ||
42 | struct symbol | 38 | struct symbol { |
43 | { | 39 | struct symbol *hash_next; |
44 | struct symbol *hash_next; | 40 | const char *name; |
45 | const char *name; | 41 | enum symbol_type type; |
46 | enum symbol_type type; | 42 | struct string_list *defn; |
47 | struct string_list *defn; | 43 | struct symbol *expansion_trail; |
48 | struct symbol *expansion_trail; | 44 | int is_extern; |
49 | int is_extern; | ||
50 | }; | 45 | }; |
51 | 46 | ||
52 | typedef struct string_list **yystype; | 47 | typedef struct string_list **yystype; |
53 | #define YYSTYPE yystype | 48 | #define YYSTYPE yystype |
54 | 49 | ||
55 | extern FILE *outfile, *debugfile; | ||
56 | |||
57 | extern int cur_line; | 50 | extern int cur_line; |
58 | extern char *cur_filename, *output_directory; | 51 | extern char *cur_filename; |
59 | |||
60 | extern int flag_debug, flag_dump_defs, flag_warnings; | ||
61 | extern int checksum_version, kernel_version; | ||
62 | |||
63 | extern int want_brace_phrase, want_exp_phrase, discard_phrase_contents; | ||
64 | extern struct string_list *current_list, *next_list; | ||
65 | |||
66 | 52 | ||
67 | struct symbol *find_symbol(const char *name, enum symbol_type ns); | 53 | struct symbol *find_symbol(const char *name, enum symbol_type ns); |
68 | struct symbol *add_symbol(const char *name, enum symbol_type type, | 54 | struct symbol *add_symbol(const char *name, enum symbol_type type, |
69 | struct string_list *defn, int is_extern); | 55 | struct string_list *defn, int is_extern); |
70 | void export_symbol(const char *); | 56 | void export_symbol(const char *); |
71 | 57 | ||
72 | struct string_list *reset_list(void); | ||
73 | void free_list(struct string_list *s, struct string_list *e); | ||
74 | void free_node(struct string_list *list); | 58 | void free_node(struct string_list *list); |
59 | void free_list(struct string_list *s, struct string_list *e); | ||
75 | struct string_list *copy_node(struct string_list *); | 60 | struct string_list *copy_node(struct string_list *); |
76 | struct string_list *copy_list(struct string_list *s, struct string_list *e); | ||
77 | int equal_list(struct string_list *a, struct string_list *b); | ||
78 | void print_list(FILE *, struct string_list *list); | ||
79 | 61 | ||
80 | int yylex(void); | 62 | int yylex(void); |
81 | int yyparse(void); | 63 | int yyparse(void); |
82 | 64 | ||
83 | void error_with_pos(const char *, ...); | 65 | void error_with_pos(const char *, ...); |
84 | 66 | ||
85 | #define version(a,b,c) ((a << 16) | (b << 8) | (c)) | ||
86 | |||
87 | /*----------------------------------------------------------------------*/ | 67 | /*----------------------------------------------------------------------*/ |
88 | |||
89 | #define MODUTILS_VERSION "<in-kernel>" | ||
90 | |||
91 | #define xmalloc(size) ({ void *__ptr = malloc(size); \ | 68 | #define xmalloc(size) ({ void *__ptr = malloc(size); \ |
92 | if(!__ptr && size != 0) { \ | 69 | if(!__ptr && size != 0) { \ |
93 | fprintf(stderr, "out of memory\n"); \ | 70 | fprintf(stderr, "out of memory\n"); \ |
@@ -101,4 +78,4 @@ void error_with_pos(const char *, ...); | |||
101 | } \ | 78 | } \ |
102 | __str; }) | 79 | __str; }) |
103 | 80 | ||
104 | #endif /* genksyms.h */ | 81 | #endif /* genksyms.h */ |
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 5760e057ecba..e6499db4c8cc 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Kernel configuration targets | 2 | # Kernel configuration targets |
3 | # These targets are used from top-level makefile | 3 | # These targets are used from top-level makefile |
4 | 4 | ||
5 | .PHONY: oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config | 5 | PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config |
6 | 6 | ||
7 | xconfig: $(obj)/qconf | 7 | xconfig: $(obj)/qconf |
8 | $< arch/$(ARCH)/Kconfig | 8 | $< arch/$(ARCH)/Kconfig |
@@ -42,7 +42,7 @@ update-po-config: $(obj)/kxgettext | |||
42 | $(Q)rm -f arch/um/Kconfig_arch | 42 | $(Q)rm -f arch/um/Kconfig_arch |
43 | $(Q)rm -f scripts/kconfig/linux_*.pot scripts/kconfig/config.pot | 43 | $(Q)rm -f scripts/kconfig/linux_*.pot scripts/kconfig/config.pot |
44 | 44 | ||
45 | .PHONY: randconfig allyesconfig allnoconfig allmodconfig defconfig | 45 | PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig |
46 | 46 | ||
47 | randconfig: $(obj)/conf | 47 | randconfig: $(obj)/conf |
48 | $< -r arch/$(ARCH)/Kconfig | 48 | $< -r arch/$(ARCH)/Kconfig |
@@ -78,7 +78,7 @@ help: | |||
78 | @echo ' defconfig - New config with default answer to all options' | 78 | @echo ' defconfig - New config with default answer to all options' |
79 | @echo ' allmodconfig - New config selecting modules when possible' | 79 | @echo ' allmodconfig - New config selecting modules when possible' |
80 | @echo ' allyesconfig - New config where all options are accepted with yes' | 80 | @echo ' allyesconfig - New config where all options are accepted with yes' |
81 | @echo ' allnoconfig - New minimal config' | 81 | @echo ' allnoconfig - New config where all options are answered with no' |
82 | 82 | ||
83 | # =========================================================================== | 83 | # =========================================================================== |
84 | # Shared Makefile for the various kconfig executables: | 84 | # Shared Makefile for the various kconfig executables: |
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index b0cbbe2e41bb..1b8882ddbc74 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c | |||
@@ -374,6 +374,7 @@ int conf_write(const char *name) | |||
374 | out_h = fopen(".tmpconfig.h", "w"); | 374 | out_h = fopen(".tmpconfig.h", "w"); |
375 | if (!out_h) | 375 | if (!out_h) |
376 | return 1; | 376 | return 1; |
377 | file_write_dep(NULL); | ||
377 | } | 378 | } |
378 | sym = sym_lookup("KERNELVERSION", 0); | 379 | sym = sym_lookup("KERNELVERSION", 0); |
379 | sym_calc_value(sym); | 380 | sym_calc_value(sym); |
@@ -512,7 +513,6 @@ int conf_write(const char *name) | |||
512 | if (out_h) { | 513 | if (out_h) { |
513 | fclose(out_h); | 514 | fclose(out_h); |
514 | rename(".tmpconfig.h", "include/linux/autoconf.h"); | 515 | rename(".tmpconfig.h", "include/linux/autoconf.h"); |
515 | file_write_dep(NULL); | ||
516 | } | 516 | } |
517 | if (!name || basename != conf_def_filename) { | 517 | if (!name || basename != conf_def_filename) { |
518 | if (!name) | 518 | if (!name) |
diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile index bbf4887cff74..a8b026326247 100644 --- a/scripts/kconfig/lxdialog/Makefile +++ b/scripts/kconfig/lxdialog/Makefile | |||
@@ -7,10 +7,10 @@ check-lxdialog := $(srctree)/$(src)/check-lxdialog.sh | |||
7 | # we really need to do so. (Do not call gcc as part of make mrproper) | 7 | # we really need to do so. (Do not call gcc as part of make mrproper) |
8 | HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) | 8 | HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) |
9 | HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) | 9 | HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) |
10 | |||
11 | HOST_EXTRACFLAGS += -DLOCALE | ||
12 | 10 | ||
13 | .PHONY: dochecklxdialog | 11 | HOST_EXTRACFLAGS += -DLOCALE |
12 | |||
13 | PHONY += dochecklxdialog | ||
14 | $(obj)/dochecklxdialog: | 14 | $(obj)/dochecklxdialog: |
15 | $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES) | 15 | $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES) |
16 | 16 | ||
diff --git a/scripts/mkmakefile b/scripts/mkmakefile index c4d621b30d0d..a22cbedd3b3e 100644 --- a/scripts/mkmakefile +++ b/scripts/mkmakefile | |||
@@ -21,11 +21,13 @@ KERNELOUTPUT := $2 | |||
21 | 21 | ||
22 | MAKEFLAGS += --no-print-directory | 22 | MAKEFLAGS += --no-print-directory |
23 | 23 | ||
24 | .PHONY: all \$(MAKECMDGOALS) | ||
25 | |||
24 | all: | 26 | all: |
25 | \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) | 27 | \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) |
26 | 28 | ||
27 | %:: | 29 | Makefile:; |
28 | \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@ | ||
29 | 30 | ||
31 | \$(filter-out all Makefile,\$(MAKECMDGOALS)) %/: | ||
32 | \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@ | ||
30 | EOF | 33 | EOF |
31 | |||
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index c164b230ad6f..84e21201f3c0 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -34,7 +34,7 @@ typedef uint16_t __u16; | |||
34 | typedef unsigned char __u8; | 34 | typedef unsigned char __u8; |
35 | 35 | ||
36 | /* Big exception to the "don't include kernel headers into userspace, which | 36 | /* Big exception to the "don't include kernel headers into userspace, which |
37 | * even potentially has different endianness and word sizes, since | 37 | * even potentially has different endianness and word sizes, since |
38 | * we handle those differences explicitly below */ | 38 | * we handle those differences explicitly below */ |
39 | #include "../../include/linux/mod_devicetable.h" | 39 | #include "../../include/linux/mod_devicetable.h" |
40 | #include "../../include/linux/input.h" | 40 | #include "../../include/linux/input.h" |
@@ -153,8 +153,8 @@ static void do_usb_table(void *symval, unsigned long size, | |||
153 | const unsigned long id_size = sizeof(struct usb_device_id); | 153 | const unsigned long id_size = sizeof(struct usb_device_id); |
154 | 154 | ||
155 | if (size % id_size || size < id_size) { | 155 | if (size % id_size || size < id_size) { |
156 | fprintf(stderr, "*** Warning: %s ids %lu bad size " | 156 | warn("%s ids %lu bad size " |
157 | "(each on %lu)\n", mod->name, size, id_size); | 157 | "(each on %lu)\n", mod->name, size, id_size); |
158 | } | 158 | } |
159 | /* Leave last one: it's the terminator. */ | 159 | /* Leave last one: it's the terminator. */ |
160 | size -= id_size; | 160 | size -= id_size; |
@@ -217,9 +217,8 @@ static int do_pci_entry(const char *filename, | |||
217 | if ((baseclass_mask != 0 && baseclass_mask != 0xFF) | 217 | if ((baseclass_mask != 0 && baseclass_mask != 0xFF) |
218 | || (subclass_mask != 0 && subclass_mask != 0xFF) | 218 | || (subclass_mask != 0 && subclass_mask != 0xFF) |
219 | || (interface_mask != 0 && interface_mask != 0xFF)) { | 219 | || (interface_mask != 0 && interface_mask != 0xFF)) { |
220 | fprintf(stderr, | 220 | warn("Can't handle masks in %s:%04X\n", |
221 | "*** Warning: Can't handle masks in %s:%04X\n", | 221 | filename, id->class_mask); |
222 | filename, id->class_mask); | ||
223 | return 0; | 222 | return 0; |
224 | } | 223 | } |
225 | 224 | ||
@@ -229,7 +228,7 @@ static int do_pci_entry(const char *filename, | |||
229 | return 1; | 228 | return 1; |
230 | } | 229 | } |
231 | 230 | ||
232 | /* looks like: "ccw:tNmNdtNdmN" */ | 231 | /* looks like: "ccw:tNmNdtNdmN" */ |
233 | static int do_ccw_entry(const char *filename, | 232 | static int do_ccw_entry(const char *filename, |
234 | struct ccw_device_id *id, char *alias) | 233 | struct ccw_device_id *id, char *alias) |
235 | { | 234 | { |
@@ -445,8 +444,8 @@ static void do_table(void *symval, unsigned long size, | |||
445 | int (*do_entry)(const char *, void *entry, char *alias) = function; | 444 | int (*do_entry)(const char *, void *entry, char *alias) = function; |
446 | 445 | ||
447 | if (size % id_size || size < id_size) { | 446 | if (size % id_size || size < id_size) { |
448 | fprintf(stderr, "*** Warning: %s ids %lu bad size " | 447 | warn("%s ids %lu bad size " |
449 | "(each on %lu)\n", mod->name, size, id_size); | 448 | "(each on %lu)\n", mod->name, size, id_size); |
450 | } | 449 | } |
451 | /* Leave last one: it's the terminator. */ | 450 | /* Leave last one: it's the terminator. */ |
452 | size -= id_size; | 451 | size -= id_size; |
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c index de2aabf89fb3..3c92c83733f4 100644 --- a/scripts/mod/mk_elfconfig.c +++ b/scripts/mod/mk_elfconfig.c | |||
@@ -6,7 +6,7 @@ | |||
6 | int | 6 | int |
7 | main(int argc, char **argv) | 7 | main(int argc, char **argv) |
8 | { | 8 | { |
9 | unsigned char ei[EI_NIDENT]; | 9 | unsigned char ei[EI_NIDENT]; |
10 | union { short s; char c[2]; } endian_test; | 10 | union { short s; char c[2]; } endian_test; |
11 | 11 | ||
12 | if (argc != 2) { | 12 | if (argc != 2) { |
@@ -57,7 +57,7 @@ main(int argc, char **argv) | |||
57 | 57 | ||
58 | if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)) | 58 | if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)) |
59 | printf("#define MODULE_SYMBOL_PREFIX \"_\"\n"); | 59 | printf("#define MODULE_SYMBOL_PREFIX \"_\"\n"); |
60 | else | 60 | else |
61 | printf("#define MODULE_SYMBOL_PREFIX \"\"\n"); | 61 | printf("#define MODULE_SYMBOL_PREFIX \"\"\n"); |
62 | 62 | ||
63 | return 0; | 63 | return 0; |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index b8b2a560b26b..0b92ddff26fd 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright 2003 Kai Germaschewski | 3 | * Copyright 2003 Kai Germaschewski |
4 | * Copyright 2002-2004 Rusty Russell, IBM Corporation | 4 | * Copyright 2002-2004 Rusty Russell, IBM Corporation |
5 | * | 5 | * Copyright 2006 Sam Ravnborg |
6 | * Based in part on module-init-tools/depmod.c,file2alias | 6 | * Based in part on module-init-tools/depmod.c,file2alias |
7 | * | 7 | * |
8 | * This software may be used and distributed according to the terms | 8 | * This software may be used and distributed according to the terms |
@@ -20,9 +20,10 @@ int modversions = 0; | |||
20 | int have_vmlinux = 0; | 20 | int have_vmlinux = 0; |
21 | /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ | 21 | /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ |
22 | static int all_versions = 0; | 22 | static int all_versions = 0; |
23 | /* If we are modposting external module set to 1 */ | ||
24 | static int external_module = 0; | ||
23 | 25 | ||
24 | void | 26 | void fatal(const char *fmt, ...) |
25 | fatal(const char *fmt, ...) | ||
26 | { | 27 | { |
27 | va_list arglist; | 28 | va_list arglist; |
28 | 29 | ||
@@ -35,8 +36,7 @@ fatal(const char *fmt, ...) | |||
35 | exit(1); | 36 | exit(1); |
36 | } | 37 | } |
37 | 38 | ||
38 | void | 39 | void warn(const char *fmt, ...) |
39 | warn(const char *fmt, ...) | ||
40 | { | 40 | { |
41 | va_list arglist; | 41 | va_list arglist; |
42 | 42 | ||
@@ -47,6 +47,18 @@ warn(const char *fmt, ...) | |||
47 | va_end(arglist); | 47 | va_end(arglist); |
48 | } | 48 | } |
49 | 49 | ||
50 | static int is_vmlinux(const char *modname) | ||
51 | { | ||
52 | const char *myname; | ||
53 | |||
54 | if ((myname = strrchr(modname, '/'))) | ||
55 | myname++; | ||
56 | else | ||
57 | myname = modname; | ||
58 | |||
59 | return strcmp(myname, "vmlinux") == 0; | ||
60 | } | ||
61 | |||
50 | void *do_nofail(void *ptr, const char *expr) | 62 | void *do_nofail(void *ptr, const char *expr) |
51 | { | 63 | { |
52 | if (!ptr) { | 64 | if (!ptr) { |
@@ -59,8 +71,7 @@ void *do_nofail(void *ptr, const char *expr) | |||
59 | 71 | ||
60 | static struct module *modules; | 72 | static struct module *modules; |
61 | 73 | ||
62 | struct module * | 74 | static struct module *find_module(char *modname) |
63 | find_module(char *modname) | ||
64 | { | 75 | { |
65 | struct module *mod; | 76 | struct module *mod; |
66 | 77 | ||
@@ -70,12 +81,11 @@ find_module(char *modname) | |||
70 | return mod; | 81 | return mod; |
71 | } | 82 | } |
72 | 83 | ||
73 | struct module * | 84 | static struct module *new_module(char *modname) |
74 | new_module(char *modname) | ||
75 | { | 85 | { |
76 | struct module *mod; | 86 | struct module *mod; |
77 | char *p, *s; | 87 | char *p, *s; |
78 | 88 | ||
79 | mod = NOFAIL(malloc(sizeof(*mod))); | 89 | mod = NOFAIL(malloc(sizeof(*mod))); |
80 | memset(mod, 0, sizeof(*mod)); | 90 | memset(mod, 0, sizeof(*mod)); |
81 | p = NOFAIL(strdup(modname)); | 91 | p = NOFAIL(strdup(modname)); |
@@ -104,6 +114,10 @@ struct symbol { | |||
104 | unsigned int crc; | 114 | unsigned int crc; |
105 | int crc_valid; | 115 | int crc_valid; |
106 | unsigned int weak:1; | 116 | unsigned int weak:1; |
117 | unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ | ||
118 | unsigned int kernel:1; /* 1 if symbol is from kernel | ||
119 | * (only for external modules) **/ | ||
120 | unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ | ||
107 | char name[0]; | 121 | char name[0]; |
108 | }; | 122 | }; |
109 | 123 | ||
@@ -122,11 +136,12 @@ static inline unsigned int tdb_hash(const char *name) | |||
122 | return (1103515243 * value + 12345); | 136 | return (1103515243 * value + 12345); |
123 | } | 137 | } |
124 | 138 | ||
125 | /* Allocate a new symbols for use in the hash of exported symbols or | 139 | /** |
126 | * the list of unresolved symbols per module */ | 140 | * Allocate a new symbols for use in the hash of exported symbols or |
127 | 141 | * the list of unresolved symbols per module | |
128 | struct symbol * | 142 | **/ |
129 | alloc_symbol(const char *name, unsigned int weak, struct symbol *next) | 143 | static struct symbol *alloc_symbol(const char *name, unsigned int weak, |
144 | struct symbol *next) | ||
130 | { | 145 | { |
131 | struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); | 146 | struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); |
132 | 147 | ||
@@ -138,9 +153,7 @@ alloc_symbol(const char *name, unsigned int weak, struct symbol *next) | |||
138 | } | 153 | } |
139 | 154 | ||
140 | /* For the hash of exported symbols */ | 155 | /* For the hash of exported symbols */ |
141 | 156 | static struct symbol *new_symbol(const char *name, struct module *module) | |
142 | void | ||
143 | new_symbol(const char *name, struct module *module, unsigned int *crc) | ||
144 | { | 157 | { |
145 | unsigned int hash; | 158 | unsigned int hash; |
146 | struct symbol *new; | 159 | struct symbol *new; |
@@ -148,14 +161,10 @@ new_symbol(const char *name, struct module *module, unsigned int *crc) | |||
148 | hash = tdb_hash(name) % SYMBOL_HASH_SIZE; | 161 | hash = tdb_hash(name) % SYMBOL_HASH_SIZE; |
149 | new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); | 162 | new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); |
150 | new->module = module; | 163 | new->module = module; |
151 | if (crc) { | 164 | return new; |
152 | new->crc = *crc; | ||
153 | new->crc_valid = 1; | ||
154 | } | ||
155 | } | 165 | } |
156 | 166 | ||
157 | struct symbol * | 167 | static struct symbol *find_symbol(const char *name) |
158 | find_symbol(const char *name) | ||
159 | { | 168 | { |
160 | struct symbol *s; | 169 | struct symbol *s; |
161 | 170 | ||
@@ -170,25 +179,42 @@ find_symbol(const char *name) | |||
170 | return NULL; | 179 | return NULL; |
171 | } | 180 | } |
172 | 181 | ||
173 | /* Add an exported symbol - it may have already been added without a | 182 | /** |
174 | * CRC, in this case just update the CRC */ | 183 | * Add an exported symbol - it may have already been added without a |
175 | void | 184 | * CRC, in this case just update the CRC |
176 | add_exported_symbol(const char *name, struct module *module, unsigned int *crc) | 185 | **/ |
186 | static struct symbol *sym_add_exported(const char *name, struct module *mod) | ||
177 | { | 187 | { |
178 | struct symbol *s = find_symbol(name); | 188 | struct symbol *s = find_symbol(name); |
179 | 189 | ||
180 | if (!s) { | 190 | if (!s) { |
181 | new_symbol(name, module, crc); | 191 | s = new_symbol(name, mod); |
182 | return; | 192 | } else { |
183 | } | 193 | if (!s->preloaded) { |
184 | if (crc) { | 194 | warn("%s: '%s' exported twice. Previous export " |
185 | s->crc = *crc; | 195 | "was in %s%s\n", mod->name, name, |
186 | s->crc_valid = 1; | 196 | s->module->name, |
197 | is_vmlinux(s->module->name) ?"":".ko"); | ||
198 | } | ||
187 | } | 199 | } |
200 | s->preloaded = 0; | ||
201 | s->vmlinux = is_vmlinux(mod->name); | ||
202 | s->kernel = 0; | ||
203 | return s; | ||
204 | } | ||
205 | |||
206 | static void sym_update_crc(const char *name, struct module *mod, | ||
207 | unsigned int crc) | ||
208 | { | ||
209 | struct symbol *s = find_symbol(name); | ||
210 | |||
211 | if (!s) | ||
212 | s = new_symbol(name, mod); | ||
213 | s->crc = crc; | ||
214 | s->crc_valid = 1; | ||
188 | } | 215 | } |
189 | 216 | ||
190 | void * | 217 | void *grab_file(const char *filename, unsigned long *size) |
191 | grab_file(const char *filename, unsigned long *size) | ||
192 | { | 218 | { |
193 | struct stat st; | 219 | struct stat st; |
194 | void *map; | 220 | void *map; |
@@ -207,13 +233,12 @@ grab_file(const char *filename, unsigned long *size) | |||
207 | return map; | 233 | return map; |
208 | } | 234 | } |
209 | 235 | ||
210 | /* | 236 | /** |
211 | Return a copy of the next line in a mmap'ed file. | 237 | * Return a copy of the next line in a mmap'ed file. |
212 | spaces in the beginning of the line is trimmed away. | 238 | * spaces in the beginning of the line is trimmed away. |
213 | Return a pointer to a static buffer. | 239 | * Return a pointer to a static buffer. |
214 | */ | 240 | **/ |
215 | char* | 241 | char* get_next_line(unsigned long *pos, void *file, unsigned long size) |
216 | get_next_line(unsigned long *pos, void *file, unsigned long size) | ||
217 | { | 242 | { |
218 | static char line[4096]; | 243 | static char line[4096]; |
219 | int skip = 1; | 244 | int skip = 1; |
@@ -243,14 +268,12 @@ get_next_line(unsigned long *pos, void *file, unsigned long size) | |||
243 | return NULL; | 268 | return NULL; |
244 | } | 269 | } |
245 | 270 | ||
246 | void | 271 | void release_file(void *file, unsigned long size) |
247 | release_file(void *file, unsigned long size) | ||
248 | { | 272 | { |
249 | munmap(file, size); | 273 | munmap(file, size); |
250 | } | 274 | } |
251 | 275 | ||
252 | void | 276 | static void parse_elf(struct elf_info *info, const char *filename) |
253 | parse_elf(struct elf_info *info, const char *filename) | ||
254 | { | 277 | { |
255 | unsigned int i; | 278 | unsigned int i; |
256 | Elf_Ehdr *hdr = info->hdr; | 279 | Elf_Ehdr *hdr = info->hdr; |
@@ -297,14 +320,13 @@ parse_elf(struct elf_info *info, const char *filename) | |||
297 | continue; | 320 | continue; |
298 | 321 | ||
299 | info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; | 322 | info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; |
300 | info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset | 323 | info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset |
301 | + sechdrs[i].sh_size; | 324 | + sechdrs[i].sh_size; |
302 | info->strtab = (void *)hdr + | 325 | info->strtab = (void *)hdr + |
303 | sechdrs[sechdrs[i].sh_link].sh_offset; | 326 | sechdrs[sechdrs[i].sh_link].sh_offset; |
304 | } | 327 | } |
305 | if (!info->symtab_start) { | 328 | if (!info->symtab_start) { |
306 | fprintf(stderr, "modpost: %s no symtab?\n", filename); | 329 | fatal("%s has no symtab?\n", filename); |
307 | abort(); | ||
308 | } | 330 | } |
309 | /* Fix endianness in symbols */ | 331 | /* Fix endianness in symbols */ |
310 | for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { | 332 | for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { |
@@ -316,36 +338,31 @@ parse_elf(struct elf_info *info, const char *filename) | |||
316 | return; | 338 | return; |
317 | 339 | ||
318 | truncated: | 340 | truncated: |
319 | fprintf(stderr, "modpost: %s is truncated.\n", filename); | 341 | fatal("%s is truncated.\n", filename); |
320 | abort(); | ||
321 | } | 342 | } |
322 | 343 | ||
323 | void | 344 | static void parse_elf_finish(struct elf_info *info) |
324 | parse_elf_finish(struct elf_info *info) | ||
325 | { | 345 | { |
326 | release_file(info->hdr, info->size); | 346 | release_file(info->hdr, info->size); |
327 | } | 347 | } |
328 | 348 | ||
329 | #define CRC_PFX "__crc_" | 349 | #define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_" |
330 | #define KSYMTAB_PFX "__ksymtab_" | 350 | #define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_" |
331 | 351 | ||
332 | void | 352 | static void handle_modversions(struct module *mod, struct elf_info *info, |
333 | handle_modversions(struct module *mod, struct elf_info *info, | 353 | Elf_Sym *sym, const char *symname) |
334 | Elf_Sym *sym, const char *symname) | ||
335 | { | 354 | { |
336 | unsigned int crc; | 355 | unsigned int crc; |
337 | 356 | ||
338 | switch (sym->st_shndx) { | 357 | switch (sym->st_shndx) { |
339 | case SHN_COMMON: | 358 | case SHN_COMMON: |
340 | fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n", | 359 | warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name); |
341 | symname, mod->name); | ||
342 | break; | 360 | break; |
343 | case SHN_ABS: | 361 | case SHN_ABS: |
344 | /* CRC'd symbol */ | 362 | /* CRC'd symbol */ |
345 | if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { | 363 | if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { |
346 | crc = (unsigned int) sym->st_value; | 364 | crc = (unsigned int) sym->st_value; |
347 | add_exported_symbol(symname + strlen(CRC_PFX), | 365 | sym_update_crc(symname + strlen(CRC_PFX), mod, crc); |
348 | mod, &crc); | ||
349 | } | 366 | } |
350 | break; | 367 | break; |
351 | case SHN_UNDEF: | 368 | case SHN_UNDEF: |
@@ -370,15 +387,15 @@ handle_modversions(struct module *mod, struct elf_info *info, | |||
370 | /* Ignore register directives. */ | 387 | /* Ignore register directives. */ |
371 | if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) | 388 | if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) |
372 | break; | 389 | break; |
373 | if (symname[0] == '.') { | 390 | if (symname[0] == '.') { |
374 | char *munged = strdup(symname); | 391 | char *munged = strdup(symname); |
375 | munged[0] = '_'; | 392 | munged[0] = '_'; |
376 | munged[1] = toupper(munged[1]); | 393 | munged[1] = toupper(munged[1]); |
377 | symname = munged; | 394 | symname = munged; |
378 | } | 395 | } |
379 | } | 396 | } |
380 | #endif | 397 | #endif |
381 | 398 | ||
382 | if (memcmp(symname, MODULE_SYMBOL_PREFIX, | 399 | if (memcmp(symname, MODULE_SYMBOL_PREFIX, |
383 | strlen(MODULE_SYMBOL_PREFIX)) == 0) | 400 | strlen(MODULE_SYMBOL_PREFIX)) == 0) |
384 | mod->unres = alloc_symbol(symname + | 401 | mod->unres = alloc_symbol(symname + |
@@ -389,8 +406,7 @@ handle_modversions(struct module *mod, struct elf_info *info, | |||
389 | default: | 406 | default: |
390 | /* All exported symbols */ | 407 | /* All exported symbols */ |
391 | if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { | 408 | if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { |
392 | add_exported_symbol(symname + strlen(KSYMTAB_PFX), | 409 | sym_add_exported(symname + strlen(KSYMTAB_PFX), mod); |
393 | mod, NULL); | ||
394 | } | 410 | } |
395 | if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) | 411 | if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) |
396 | mod->has_init = 1; | 412 | mod->has_init = 1; |
@@ -400,20 +416,9 @@ handle_modversions(struct module *mod, struct elf_info *info, | |||
400 | } | 416 | } |
401 | } | 417 | } |
402 | 418 | ||
403 | int | 419 | /** |
404 | is_vmlinux(const char *modname) | 420 | * Parse tag=value strings from .modinfo section |
405 | { | 421 | **/ |
406 | const char *myname; | ||
407 | |||
408 | if ((myname = strrchr(modname, '/'))) | ||
409 | myname++; | ||
410 | else | ||
411 | myname = modname; | ||
412 | |||
413 | return strcmp(myname, "vmlinux") == 0; | ||
414 | } | ||
415 | |||
416 | /* Parse tag=value strings from .modinfo section */ | ||
417 | static char *next_string(char *string, unsigned long *secsize) | 422 | static char *next_string(char *string, unsigned long *secsize) |
418 | { | 423 | { |
419 | /* Skip non-zero chars */ | 424 | /* Skip non-zero chars */ |
@@ -446,8 +451,418 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, | |||
446 | return NULL; | 451 | return NULL; |
447 | } | 452 | } |
448 | 453 | ||
449 | void | 454 | /** |
450 | read_symbols(char *modname) | 455 | * Test if string s ends in string sub |
456 | * return 0 if match | ||
457 | **/ | ||
458 | static int strrcmp(const char *s, const char *sub) | ||
459 | { | ||
460 | int slen, sublen; | ||
461 | |||
462 | if (!s || !sub) | ||
463 | return 1; | ||
464 | |||
465 | slen = strlen(s); | ||
466 | sublen = strlen(sub); | ||
467 | |||
468 | if ((slen == 0) || (sublen == 0)) | ||
469 | return 1; | ||
470 | |||
471 | if (sublen > slen) | ||
472 | return 1; | ||
473 | |||
474 | return memcmp(s + slen - sublen, sub, sublen); | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * Whitelist to allow certain references to pass with no warning. | ||
479 | * Pattern 1: | ||
480 | * If a module parameter is declared __initdata and permissions=0 | ||
481 | * then this is legal despite the warning generated. | ||
482 | * We cannot see value of permissions here, so just ignore | ||
483 | * this pattern. | ||
484 | * The pattern is identified by: | ||
485 | * tosec = .init.data | ||
486 | * fromsec = .data* | ||
487 | * atsym =__param* | ||
488 | * | ||
489 | * Pattern 2: | ||
490 | * Many drivers utilise a *_driver container with references to | ||
491 | * add, remove, probe functions etc. | ||
492 | * These functions may often be marked __init and we do not want to | ||
493 | * warn here. | ||
494 | * the pattern is identified by: | ||
495 | * tosec = .init.text | .exit.text | ||
496 | * fromsec = .data | ||
497 | * atsym = *_driver, *_ops, *_probe, *probe_one | ||
498 | **/ | ||
499 | static int secref_whitelist(const char *tosec, const char *fromsec, | ||
500 | const char *atsym) | ||
501 | { | ||
502 | int f1 = 1, f2 = 1; | ||
503 | const char **s; | ||
504 | const char *pat2sym[] = { | ||
505 | "_driver", | ||
506 | "_ops", | ||
507 | "_probe", | ||
508 | "_probe_one", | ||
509 | NULL | ||
510 | }; | ||
511 | |||
512 | /* Check for pattern 1 */ | ||
513 | if (strcmp(tosec, ".init.data") != 0) | ||
514 | f1 = 0; | ||
515 | if (strncmp(fromsec, ".data", strlen(".data")) != 0) | ||
516 | f1 = 0; | ||
517 | if (strncmp(atsym, "__param", strlen("__param")) != 0) | ||
518 | f1 = 0; | ||
519 | |||
520 | if (f1) | ||
521 | return f1; | ||
522 | |||
523 | /* Check for pattern 2 */ | ||
524 | if ((strcmp(tosec, ".init.text") != 0) && | ||
525 | (strcmp(tosec, ".exit.text") != 0)) | ||
526 | f2 = 0; | ||
527 | if (strcmp(fromsec, ".data") != 0) | ||
528 | f2 = 0; | ||
529 | |||
530 | for (s = pat2sym; *s; s++) | ||
531 | if (strrcmp(atsym, *s) == 0) | ||
532 | f1 = 1; | ||
533 | |||
534 | return f1 && f2; | ||
535 | } | ||
536 | |||
537 | /** | ||
538 | * Find symbol based on relocation record info. | ||
539 | * In some cases the symbol supplied is a valid symbol so | ||
540 | * return refsym. If st_name != 0 we assume this is a valid symbol. | ||
541 | * In other cases the symbol needs to be looked up in the symbol table | ||
542 | * based on section and address. | ||
543 | * **/ | ||
544 | static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, | ||
545 | Elf_Sym *relsym) | ||
546 | { | ||
547 | Elf_Sym *sym; | ||
548 | |||
549 | if (relsym->st_name != 0) | ||
550 | return relsym; | ||
551 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { | ||
552 | if (sym->st_shndx != relsym->st_shndx) | ||
553 | continue; | ||
554 | if (sym->st_value == addr) | ||
555 | return sym; | ||
556 | } | ||
557 | return NULL; | ||
558 | } | ||
559 | |||
560 | /* | ||
561 | * Find symbols before or equal addr and after addr - in the section sec. | ||
562 | * If we find two symbols with equal offset prefer one with a valid name. | ||
563 | * The ELF format may have a better way to detect what type of symbol | ||
564 | * it is, but this works for now. | ||
565 | **/ | ||
566 | static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, | ||
567 | const char *sec, | ||
568 | Elf_Sym **before, Elf_Sym **after) | ||
569 | { | ||
570 | Elf_Sym *sym; | ||
571 | Elf_Ehdr *hdr = elf->hdr; | ||
572 | Elf_Addr beforediff = ~0; | ||
573 | Elf_Addr afterdiff = ~0; | ||
574 | const char *secstrings = (void *)hdr + | ||
575 | elf->sechdrs[hdr->e_shstrndx].sh_offset; | ||
576 | |||
577 | *before = NULL; | ||
578 | *after = NULL; | ||
579 | |||
580 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { | ||
581 | const char *symsec; | ||
582 | |||
583 | if (sym->st_shndx >= SHN_LORESERVE) | ||
584 | continue; | ||
585 | symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name; | ||
586 | if (strcmp(symsec, sec) != 0) | ||
587 | continue; | ||
588 | if (sym->st_value <= addr) { | ||
589 | if ((addr - sym->st_value) < beforediff) { | ||
590 | beforediff = addr - sym->st_value; | ||
591 | *before = sym; | ||
592 | } | ||
593 | else if ((addr - sym->st_value) == beforediff) { | ||
594 | /* equal offset, valid name? */ | ||
595 | const char *name = elf->strtab + sym->st_name; | ||
596 | if (name && strlen(name)) | ||
597 | *before = sym; | ||
598 | } | ||
599 | } | ||
600 | else | ||
601 | { | ||
602 | if ((sym->st_value - addr) < afterdiff) { | ||
603 | afterdiff = sym->st_value - addr; | ||
604 | *after = sym; | ||
605 | } | ||
606 | else if ((sym->st_value - addr) == afterdiff) { | ||
607 | /* equal offset, valid name? */ | ||
608 | const char *name = elf->strtab + sym->st_name; | ||
609 | if (name && strlen(name)) | ||
610 | *after = sym; | ||
611 | } | ||
612 | } | ||
613 | } | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * Print a warning about a section mismatch. | ||
618 | * Try to find symbols near it so user can find it. | ||
619 | * Check whitelist before warning - it may be a false positive. | ||
620 | **/ | ||
621 | static void warn_sec_mismatch(const char *modname, const char *fromsec, | ||
622 | struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) | ||
623 | { | ||
624 | const char *refsymname = ""; | ||
625 | Elf_Sym *before, *after; | ||
626 | Elf_Sym *refsym; | ||
627 | Elf_Ehdr *hdr = elf->hdr; | ||
628 | Elf_Shdr *sechdrs = elf->sechdrs; | ||
629 | const char *secstrings = (void *)hdr + | ||
630 | sechdrs[hdr->e_shstrndx].sh_offset; | ||
631 | const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name; | ||
632 | |||
633 | find_symbols_between(elf, r.r_offset, fromsec, &before, &after); | ||
634 | |||
635 | refsym = find_elf_symbol(elf, r.r_addend, sym); | ||
636 | if (refsym && strlen(elf->strtab + refsym->st_name)) | ||
637 | refsymname = elf->strtab + refsym->st_name; | ||
638 | |||
639 | /* check whitelist - we may ignore it */ | ||
640 | if (before && | ||
641 | secref_whitelist(secname, fromsec, elf->strtab + before->st_name)) | ||
642 | return; | ||
643 | |||
644 | if (before && after) { | ||
645 | warn("%s - Section mismatch: reference to %s:%s from %s " | ||
646 | "between '%s' (at offset 0x%llx) and '%s'\n", | ||
647 | modname, secname, refsymname, fromsec, | ||
648 | elf->strtab + before->st_name, | ||
649 | (long long)r.r_offset, | ||
650 | elf->strtab + after->st_name); | ||
651 | } else if (before) { | ||
652 | warn("%s - Section mismatch: reference to %s:%s from %s " | ||
653 | "after '%s' (at offset 0x%llx)\n", | ||
654 | modname, secname, refsymname, fromsec, | ||
655 | elf->strtab + before->st_name, | ||
656 | (long long)r.r_offset); | ||
657 | } else if (after) { | ||
658 | warn("%s - Section mismatch: reference to %s:%s from %s " | ||
659 | "before '%s' (at offset -0x%llx)\n", | ||
660 | modname, secname, refsymname, fromsec, | ||
661 | elf->strtab + before->st_name, | ||
662 | (long long)r.r_offset); | ||
663 | } else { | ||
664 | warn("%s - Section mismatch: reference to %s:%s from %s " | ||
665 | "(offset 0x%llx)\n", | ||
666 | modname, secname, fromsec, refsymname, | ||
667 | (long long)r.r_offset); | ||
668 | } | ||
669 | } | ||
670 | |||
671 | /** | ||
672 | * A module includes a number of sections that are discarded | ||
673 | * either when loaded or when used as built-in. | ||
674 | * For loaded modules all functions marked __init and all data | ||
675 | * marked __initdata will be discarded when the module has been intialized. | ||
676 | * Likewise for modules used built-in the sections marked __exit | ||
677 | * are discarded because __exit marked function are supposed to be called | ||
678 | * only when a moduel is unloaded which never happes for built-in modules. | ||
679 | * The check_sec_ref() function traverses all relocation records | ||
680 | * to find all references to a section that reference a section that will | ||
681 | * be discarded and warns about it. | ||
682 | **/ | ||
683 | static void check_sec_ref(struct module *mod, const char *modname, | ||
684 | struct elf_info *elf, | ||
685 | int section(const char*), | ||
686 | int section_ref_ok(const char *)) | ||
687 | { | ||
688 | int i; | ||
689 | Elf_Sym *sym; | ||
690 | Elf_Ehdr *hdr = elf->hdr; | ||
691 | Elf_Shdr *sechdrs = elf->sechdrs; | ||
692 | const char *secstrings = (void *)hdr + | ||
693 | sechdrs[hdr->e_shstrndx].sh_offset; | ||
694 | |||
695 | /* Walk through all sections */ | ||
696 | for (i = 0; i < hdr->e_shnum; i++) { | ||
697 | Elf_Rela *rela; | ||
698 | Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; | ||
699 | Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; | ||
700 | const char *name = secstrings + sechdrs[i].sh_name + | ||
701 | strlen(".rela"); | ||
702 | /* We want to process only relocation sections and not .init */ | ||
703 | if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA)) | ||
704 | continue; | ||
705 | |||
706 | for (rela = start; rela < stop; rela++) { | ||
707 | Elf_Rela r; | ||
708 | const char *secname; | ||
709 | r.r_offset = TO_NATIVE(rela->r_offset); | ||
710 | r.r_info = TO_NATIVE(rela->r_info); | ||
711 | r.r_addend = TO_NATIVE(rela->r_addend); | ||
712 | sym = elf->symtab_start + ELF_R_SYM(r.r_info); | ||
713 | /* Skip special sections */ | ||
714 | if (sym->st_shndx >= SHN_LORESERVE) | ||
715 | continue; | ||
716 | |||
717 | secname = secstrings + sechdrs[sym->st_shndx].sh_name; | ||
718 | if (section(secname)) | ||
719 | warn_sec_mismatch(modname, name, elf, sym, r); | ||
720 | } | ||
721 | } | ||
722 | } | ||
723 | |||
724 | /** | ||
725 | * Functions used only during module init is marked __init and is stored in | ||
726 | * a .init.text section. Likewise data is marked __initdata and stored in | ||
727 | * a .init.data section. | ||
728 | * If this section is one of these sections return 1 | ||
729 | * See include/linux/init.h for the details | ||
730 | **/ | ||
731 | static int init_section(const char *name) | ||
732 | { | ||
733 | if (strcmp(name, ".init") == 0) | ||
734 | return 1; | ||
735 | if (strncmp(name, ".init.", strlen(".init.")) == 0) | ||
736 | return 1; | ||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | /** | ||
741 | * Identify sections from which references to a .init section is OK. | ||
742 | * | ||
743 | * Unfortunately references to read only data that referenced .init | ||
744 | * sections had to be excluded. Almost all of these are false | ||
745 | * positives, they are created by gcc. The downside of excluding rodata | ||
746 | * is that there really are some user references from rodata to | ||
747 | * init code, e.g. drivers/video/vgacon.c: | ||
748 | * | ||
749 | * const struct consw vga_con = { | ||
750 | * con_startup: vgacon_startup, | ||
751 | * | ||
752 | * where vgacon_startup is __init. If you want to wade through the false | ||
753 | * positives, take out the check for rodata. | ||
754 | **/ | ||
755 | static int init_section_ref_ok(const char *name) | ||
756 | { | ||
757 | const char **s; | ||
758 | /* Absolute section names */ | ||
759 | const char *namelist1[] = { | ||
760 | ".init", | ||
761 | ".opd", /* see comment [OPD] at exit_section_ref_ok() */ | ||
762 | ".toc1", /* used by ppc64 */ | ||
763 | ".stab", | ||
764 | ".rodata", | ||
765 | ".text.lock", | ||
766 | "__bug_table", /* used by powerpc for BUG() */ | ||
767 | ".pci_fixup_header", | ||
768 | ".pci_fixup_final", | ||
769 | ".pdr", | ||
770 | "__param", | ||
771 | NULL | ||
772 | }; | ||
773 | /* Start of section names */ | ||
774 | const char *namelist2[] = { | ||
775 | ".init.", | ||
776 | ".altinstructions", | ||
777 | ".eh_frame", | ||
778 | ".debug", | ||
779 | NULL | ||
780 | }; | ||
781 | /* part of section name */ | ||
782 | const char *namelist3 [] = { | ||
783 | ".unwind", /* sample: IA_64.unwind.init.text */ | ||
784 | NULL | ||
785 | }; | ||
786 | |||
787 | for (s = namelist1; *s; s++) | ||
788 | if (strcmp(*s, name) == 0) | ||
789 | return 1; | ||
790 | for (s = namelist2; *s; s++) | ||
791 | if (strncmp(*s, name, strlen(*s)) == 0) | ||
792 | return 1; | ||
793 | for (s = namelist3; *s; s++) | ||
794 | if (strstr(name, *s) != NULL) | ||
795 | return 1; | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | /* | ||
800 | * Functions used only during module exit is marked __exit and is stored in | ||
801 | * a .exit.text section. Likewise data is marked __exitdata and stored in | ||
802 | * a .exit.data section. | ||
803 | * If this section is one of these sections return 1 | ||
804 | * See include/linux/init.h for the details | ||
805 | **/ | ||
806 | static int exit_section(const char *name) | ||
807 | { | ||
808 | if (strcmp(name, ".exit.text") == 0) | ||
809 | return 1; | ||
810 | if (strcmp(name, ".exit.data") == 0) | ||
811 | return 1; | ||
812 | return 0; | ||
813 | |||
814 | } | ||
815 | |||
816 | /* | ||
817 | * Identify sections from which references to a .exit section is OK. | ||
818 | * | ||
819 | * [OPD] Keith Ownes <kaos@sgi.com> commented: | ||
820 | * For our future {in}sanity, add a comment that this is the ppc .opd | ||
821 | * section, not the ia64 .opd section. | ||
822 | * ia64 .opd should not point to discarded sections. | ||
823 | **/ | ||
824 | static int exit_section_ref_ok(const char *name) | ||
825 | { | ||
826 | const char **s; | ||
827 | /* Absolute section names */ | ||
828 | const char *namelist1[] = { | ||
829 | ".exit.text", | ||
830 | ".exit.data", | ||
831 | ".init.text", | ||
832 | ".opd", /* See comment [OPD] */ | ||
833 | ".toc1", /* used by ppc64 */ | ||
834 | ".altinstructions", | ||
835 | ".pdr", | ||
836 | "__bug_table", /* used by powerpc for BUG() */ | ||
837 | ".exitcall.exit", | ||
838 | ".eh_frame", | ||
839 | ".stab", | ||
840 | NULL | ||
841 | }; | ||
842 | /* Start of section names */ | ||
843 | const char *namelist2[] = { | ||
844 | ".debug", | ||
845 | NULL | ||
846 | }; | ||
847 | /* part of section name */ | ||
848 | const char *namelist3 [] = { | ||
849 | ".unwind", /* Sample: IA_64.unwind.exit.text */ | ||
850 | NULL | ||
851 | }; | ||
852 | |||
853 | for (s = namelist1; *s; s++) | ||
854 | if (strcmp(*s, name) == 0) | ||
855 | return 1; | ||
856 | for (s = namelist2; *s; s++) | ||
857 | if (strncmp(*s, name, strlen(*s)) == 0) | ||
858 | return 1; | ||
859 | for (s = namelist3; *s; s++) | ||
860 | if (strstr(name, *s) != NULL) | ||
861 | return 1; | ||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | static void read_symbols(char *modname) | ||
451 | { | 866 | { |
452 | const char *symname; | 867 | const char *symname; |
453 | char *version; | 868 | char *version; |
@@ -462,9 +877,7 @@ read_symbols(char *modname) | |||
462 | /* When there's no vmlinux, don't print warnings about | 877 | /* When there's no vmlinux, don't print warnings about |
463 | * unresolved symbols (since there'll be too many ;) */ | 878 | * unresolved symbols (since there'll be too many ;) */ |
464 | if (is_vmlinux(modname)) { | 879 | if (is_vmlinux(modname)) { |
465 | unsigned int fake_crc = 0; | ||
466 | have_vmlinux = 1; | 880 | have_vmlinux = 1; |
467 | add_exported_symbol("struct_module", mod, &fake_crc); | ||
468 | mod->skip = 1; | 881 | mod->skip = 1; |
469 | } | 882 | } |
470 | 883 | ||
@@ -474,6 +887,8 @@ read_symbols(char *modname) | |||
474 | handle_modversions(mod, &info, sym, symname); | 887 | handle_modversions(mod, &info, sym, symname); |
475 | handle_moddevtable(mod, &info, sym, symname); | 888 | handle_moddevtable(mod, &info, sym, symname); |
476 | } | 889 | } |
890 | check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok); | ||
891 | check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok); | ||
477 | 892 | ||
478 | version = get_modinfo(info.modinfo, info.modinfo_len, "version"); | 893 | version = get_modinfo(info.modinfo, info.modinfo_len, "version"); |
479 | if (version) | 894 | if (version) |
@@ -499,21 +914,20 @@ read_symbols(char *modname) | |||
499 | * following helper, then compare to the file on disk and | 914 | * following helper, then compare to the file on disk and |
500 | * only update the later if anything changed */ | 915 | * only update the later if anything changed */ |
501 | 916 | ||
502 | void __attribute__((format(printf, 2, 3))) | 917 | void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf, |
503 | buf_printf(struct buffer *buf, const char *fmt, ...) | 918 | const char *fmt, ...) |
504 | { | 919 | { |
505 | char tmp[SZ]; | 920 | char tmp[SZ]; |
506 | int len; | 921 | int len; |
507 | va_list ap; | 922 | va_list ap; |
508 | 923 | ||
509 | va_start(ap, fmt); | 924 | va_start(ap, fmt); |
510 | len = vsnprintf(tmp, SZ, fmt, ap); | 925 | len = vsnprintf(tmp, SZ, fmt, ap); |
511 | buf_write(buf, tmp, len); | 926 | buf_write(buf, tmp, len); |
512 | va_end(ap); | 927 | va_end(ap); |
513 | } | 928 | } |
514 | 929 | ||
515 | void | 930 | void buf_write(struct buffer *buf, const char *s, int len) |
516 | buf_write(struct buffer *buf, const char *s, int len) | ||
517 | { | 931 | { |
518 | if (buf->size - buf->pos < len) { | 932 | if (buf->size - buf->pos < len) { |
519 | buf->size += len + SZ; | 933 | buf->size += len + SZ; |
@@ -523,10 +937,10 @@ buf_write(struct buffer *buf, const char *s, int len) | |||
523 | buf->pos += len; | 937 | buf->pos += len; |
524 | } | 938 | } |
525 | 939 | ||
526 | /* Header for the generated file */ | 940 | /** |
527 | 941 | * Header for the generated file | |
528 | void | 942 | **/ |
529 | add_header(struct buffer *b, struct module *mod) | 943 | static void add_header(struct buffer *b, struct module *mod) |
530 | { | 944 | { |
531 | buf_printf(b, "#include <linux/module.h>\n"); | 945 | buf_printf(b, "#include <linux/module.h>\n"); |
532 | buf_printf(b, "#include <linux/vermagic.h>\n"); | 946 | buf_printf(b, "#include <linux/vermagic.h>\n"); |
@@ -546,10 +960,10 @@ add_header(struct buffer *b, struct module *mod) | |||
546 | buf_printf(b, "};\n"); | 960 | buf_printf(b, "};\n"); |
547 | } | 961 | } |
548 | 962 | ||
549 | /* Record CRCs for unresolved symbols */ | 963 | /** |
550 | 964 | * Record CRCs for unresolved symbols | |
551 | void | 965 | **/ |
552 | add_versions(struct buffer *b, struct module *mod) | 966 | static void add_versions(struct buffer *b, struct module *mod) |
553 | { | 967 | { |
554 | struct symbol *s, *exp; | 968 | struct symbol *s, *exp; |
555 | 969 | ||
@@ -557,8 +971,8 @@ add_versions(struct buffer *b, struct module *mod) | |||
557 | exp = find_symbol(s->name); | 971 | exp = find_symbol(s->name); |
558 | if (!exp || exp->module == mod) { | 972 | if (!exp || exp->module == mod) { |
559 | if (have_vmlinux && !s->weak) | 973 | if (have_vmlinux && !s->weak) |
560 | fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " | 974 | warn("\"%s\" [%s.ko] undefined!\n", |
561 | "undefined!\n", s->name, mod->name); | 975 | s->name, mod->name); |
562 | continue; | 976 | continue; |
563 | } | 977 | } |
564 | s->module = exp->module; | 978 | s->module = exp->module; |
@@ -579,8 +993,7 @@ add_versions(struct buffer *b, struct module *mod) | |||
579 | continue; | 993 | continue; |
580 | } | 994 | } |
581 | if (!s->crc_valid) { | 995 | if (!s->crc_valid) { |
582 | fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " | 996 | warn("\"%s\" [%s.ko] has no CRC!\n", |
583 | "has no CRC!\n", | ||
584 | s->name, mod->name); | 997 | s->name, mod->name); |
585 | continue; | 998 | continue; |
586 | } | 999 | } |
@@ -590,8 +1003,8 @@ add_versions(struct buffer *b, struct module *mod) | |||
590 | buf_printf(b, "};\n"); | 1003 | buf_printf(b, "};\n"); |
591 | } | 1004 | } |
592 | 1005 | ||
593 | void | 1006 | static void add_depends(struct buffer *b, struct module *mod, |
594 | add_depends(struct buffer *b, struct module *mod, struct module *modules) | 1007 | struct module *modules) |
595 | { | 1008 | { |
596 | struct symbol *s; | 1009 | struct symbol *s; |
597 | struct module *m; | 1010 | struct module *m; |
@@ -621,8 +1034,7 @@ add_depends(struct buffer *b, struct module *mod, struct module *modules) | |||
621 | buf_printf(b, "\";\n"); | 1034 | buf_printf(b, "\";\n"); |
622 | } | 1035 | } |
623 | 1036 | ||
624 | void | 1037 | static void add_srcversion(struct buffer *b, struct module *mod) |
625 | add_srcversion(struct buffer *b, struct module *mod) | ||
626 | { | 1038 | { |
627 | if (mod->srcversion[0]) { | 1039 | if (mod->srcversion[0]) { |
628 | buf_printf(b, "\n"); | 1040 | buf_printf(b, "\n"); |
@@ -631,8 +1043,7 @@ add_srcversion(struct buffer *b, struct module *mod) | |||
631 | } | 1043 | } |
632 | } | 1044 | } |
633 | 1045 | ||
634 | void | 1046 | static void write_if_changed(struct buffer *b, const char *fname) |
635 | write_if_changed(struct buffer *b, const char *fname) | ||
636 | { | 1047 | { |
637 | char *tmp; | 1048 | char *tmp; |
638 | FILE *file; | 1049 | FILE *file; |
@@ -676,8 +1087,7 @@ write_if_changed(struct buffer *b, const char *fname) | |||
676 | fclose(file); | 1087 | fclose(file); |
677 | } | 1088 | } |
678 | 1089 | ||
679 | void | 1090 | static void read_dump(const char *fname, unsigned int kernel) |
680 | read_dump(const char *fname) | ||
681 | { | 1091 | { |
682 | unsigned long size, pos = 0; | 1092 | unsigned long size, pos = 0; |
683 | void *file = grab_file(fname, &size); | 1093 | void *file = grab_file(fname, &size); |
@@ -691,6 +1101,7 @@ read_dump(const char *fname) | |||
691 | char *symname, *modname, *d; | 1101 | char *symname, *modname, *d; |
692 | unsigned int crc; | 1102 | unsigned int crc; |
693 | struct module *mod; | 1103 | struct module *mod; |
1104 | struct symbol *s; | ||
694 | 1105 | ||
695 | if (!(symname = strchr(line, '\t'))) | 1106 | if (!(symname = strchr(line, '\t'))) |
696 | goto fail; | 1107 | goto fail; |
@@ -711,15 +1122,30 @@ read_dump(const char *fname) | |||
711 | mod = new_module(NOFAIL(strdup(modname))); | 1122 | mod = new_module(NOFAIL(strdup(modname))); |
712 | mod->skip = 1; | 1123 | mod->skip = 1; |
713 | } | 1124 | } |
714 | add_exported_symbol(symname, mod, &crc); | 1125 | s = sym_add_exported(symname, mod); |
1126 | s->kernel = kernel; | ||
1127 | s->preloaded = 1; | ||
1128 | sym_update_crc(symname, mod, crc); | ||
715 | } | 1129 | } |
716 | return; | 1130 | return; |
717 | fail: | 1131 | fail: |
718 | fatal("parse error in symbol dump file\n"); | 1132 | fatal("parse error in symbol dump file\n"); |
719 | } | 1133 | } |
720 | 1134 | ||
721 | void | 1135 | /* For normal builds always dump all symbols. |
722 | write_dump(const char *fname) | 1136 | * For external modules only dump symbols |
1137 | * that are not read from kernel Module.symvers. | ||
1138 | **/ | ||
1139 | static int dump_sym(struct symbol *sym) | ||
1140 | { | ||
1141 | if (!external_module) | ||
1142 | return 1; | ||
1143 | if (sym->vmlinux || sym->kernel) | ||
1144 | return 0; | ||
1145 | return 1; | ||
1146 | } | ||
1147 | |||
1148 | static void write_dump(const char *fname) | ||
723 | { | 1149 | { |
724 | struct buffer buf = { }; | 1150 | struct buffer buf = { }; |
725 | struct symbol *symbol; | 1151 | struct symbol *symbol; |
@@ -728,34 +1154,33 @@ write_dump(const char *fname) | |||
728 | for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { | 1154 | for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { |
729 | symbol = symbolhash[n]; | 1155 | symbol = symbolhash[n]; |
730 | while (symbol) { | 1156 | while (symbol) { |
731 | symbol = symbol->next; | 1157 | if (dump_sym(symbol)) |
732 | } | 1158 | buf_printf(&buf, "0x%08x\t%s\t%s\n", |
733 | } | 1159 | symbol->crc, symbol->name, |
734 | 1160 | symbol->module->name); | |
735 | for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { | ||
736 | symbol = symbolhash[n]; | ||
737 | while (symbol) { | ||
738 | buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc, | ||
739 | symbol->name, symbol->module->name); | ||
740 | symbol = symbol->next; | 1161 | symbol = symbol->next; |
741 | } | 1162 | } |
742 | } | 1163 | } |
743 | write_if_changed(&buf, fname); | 1164 | write_if_changed(&buf, fname); |
744 | } | 1165 | } |
745 | 1166 | ||
746 | int | 1167 | int main(int argc, char **argv) |
747 | main(int argc, char **argv) | ||
748 | { | 1168 | { |
749 | struct module *mod; | 1169 | struct module *mod; |
750 | struct buffer buf = { }; | 1170 | struct buffer buf = { }; |
751 | char fname[SZ]; | 1171 | char fname[SZ]; |
752 | char *dump_read = NULL, *dump_write = NULL; | 1172 | char *kernel_read = NULL, *module_read = NULL; |
1173 | char *dump_write = NULL; | ||
753 | int opt; | 1174 | int opt; |
754 | 1175 | ||
755 | while ((opt = getopt(argc, argv, "i:mo:a")) != -1) { | 1176 | while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) { |
756 | switch(opt) { | 1177 | switch(opt) { |
757 | case 'i': | 1178 | case 'i': |
758 | dump_read = optarg; | 1179 | kernel_read = optarg; |
1180 | break; | ||
1181 | case 'I': | ||
1182 | module_read = optarg; | ||
1183 | external_module = 1; | ||
759 | break; | 1184 | break; |
760 | case 'm': | 1185 | case 'm': |
761 | modversions = 1; | 1186 | modversions = 1; |
@@ -771,8 +1196,10 @@ main(int argc, char **argv) | |||
771 | } | 1196 | } |
772 | } | 1197 | } |
773 | 1198 | ||
774 | if (dump_read) | 1199 | if (kernel_read) |
775 | read_dump(dump_read); | 1200 | read_dump(kernel_read, 1); |
1201 | if (module_read) | ||
1202 | read_dump(module_read, 0); | ||
776 | 1203 | ||
777 | while (optind < argc) { | 1204 | while (optind < argc) { |
778 | read_symbols(argv[optind++]); | 1205 | read_symbols(argv[optind++]); |
@@ -799,4 +1226,3 @@ main(int argc, char **argv) | |||
799 | 1226 | ||
800 | return 0; | 1227 | return 0; |
801 | } | 1228 | } |
802 | |||
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 7334d839145d..b14255c72a37 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
@@ -13,20 +13,30 @@ | |||
13 | 13 | ||
14 | #if KERNEL_ELFCLASS == ELFCLASS32 | 14 | #if KERNEL_ELFCLASS == ELFCLASS32 |
15 | 15 | ||
16 | #define Elf_Ehdr Elf32_Ehdr | 16 | #define Elf_Ehdr Elf32_Ehdr |
17 | #define Elf_Shdr Elf32_Shdr | 17 | #define Elf_Shdr Elf32_Shdr |
18 | #define Elf_Sym Elf32_Sym | 18 | #define Elf_Sym Elf32_Sym |
19 | #define Elf_Addr Elf32_Addr | ||
20 | #define Elf_Section Elf32_Section | ||
19 | #define ELF_ST_BIND ELF32_ST_BIND | 21 | #define ELF_ST_BIND ELF32_ST_BIND |
20 | #define ELF_ST_TYPE ELF32_ST_TYPE | 22 | #define ELF_ST_TYPE ELF32_ST_TYPE |
21 | 23 | ||
24 | #define Elf_Rela Elf32_Rela | ||
25 | #define ELF_R_SYM ELF32_R_SYM | ||
26 | #define ELF_R_TYPE ELF32_R_TYPE | ||
22 | #else | 27 | #else |
23 | 28 | ||
24 | #define Elf_Ehdr Elf64_Ehdr | 29 | #define Elf_Ehdr Elf64_Ehdr |
25 | #define Elf_Shdr Elf64_Shdr | 30 | #define Elf_Shdr Elf64_Shdr |
26 | #define Elf_Sym Elf64_Sym | 31 | #define Elf_Sym Elf64_Sym |
32 | #define Elf_Addr Elf64_Addr | ||
33 | #define Elf_Section Elf64_Section | ||
27 | #define ELF_ST_BIND ELF64_ST_BIND | 34 | #define ELF_ST_BIND ELF64_ST_BIND |
28 | #define ELF_ST_TYPE ELF64_ST_TYPE | 35 | #define ELF_ST_TYPE ELF64_ST_TYPE |
29 | 36 | ||
37 | #define Elf_Rela Elf64_Rela | ||
38 | #define ELF_R_SYM ELF64_R_SYM | ||
39 | #define ELF_R_TYPE ELF64_R_TYPE | ||
30 | #endif | 40 | #endif |
31 | 41 | ||
32 | #if KERNEL_ELFDATA != HOST_ELFDATA | 42 | #if KERNEL_ELFDATA != HOST_ELFDATA |
@@ -91,17 +101,22 @@ struct elf_info { | |||
91 | unsigned int modinfo_len; | 101 | unsigned int modinfo_len; |
92 | }; | 102 | }; |
93 | 103 | ||
104 | /* file2alias.c */ | ||
94 | void handle_moddevtable(struct module *mod, struct elf_info *info, | 105 | void handle_moddevtable(struct module *mod, struct elf_info *info, |
95 | Elf_Sym *sym, const char *symname); | 106 | Elf_Sym *sym, const char *symname); |
96 | |||
97 | void add_moddevtable(struct buffer *buf, struct module *mod); | 107 | void add_moddevtable(struct buffer *buf, struct module *mod); |
98 | 108 | ||
109 | /* sumversion.c */ | ||
99 | void maybe_frob_rcs_version(const char *modfilename, | 110 | void maybe_frob_rcs_version(const char *modfilename, |
100 | char *version, | 111 | char *version, |
101 | void *modinfo, | 112 | void *modinfo, |
102 | unsigned long modinfo_offset); | 113 | unsigned long modinfo_offset); |
103 | void get_src_version(const char *modname, char sum[], unsigned sumlen); | 114 | void get_src_version(const char *modname, char sum[], unsigned sumlen); |
104 | 115 | ||
116 | /* from modpost.c */ | ||
105 | void *grab_file(const char *filename, unsigned long *size); | 117 | void *grab_file(const char *filename, unsigned long *size); |
106 | char* get_next_line(unsigned long *pos, void *file, unsigned long size); | 118 | char* get_next_line(unsigned long *pos, void *file, unsigned long size); |
107 | void release_file(void *file, unsigned long size); | 119 | void release_file(void *file, unsigned long size); |
120 | |||
121 | void fatal(const char *fmt, ...); | ||
122 | void warn(const char *fmt, ...); | ||
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 43271a1ca01e..8a2875689e4d 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c | |||
@@ -316,8 +316,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) | |||
316 | 316 | ||
317 | file = grab_file(cmd, &flen); | 317 | file = grab_file(cmd, &flen); |
318 | if (!file) { | 318 | if (!file) { |
319 | fprintf(stderr, "Warning: could not find %s for %s\n", | 319 | warn("could not find %s for %s\n", cmd, objfile); |
320 | cmd, objfile); | ||
321 | goto out; | 320 | goto out; |
322 | } | 321 | } |
323 | 322 | ||
@@ -355,9 +354,8 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) | |||
355 | /* Check if this file is in same dir as objfile */ | 354 | /* Check if this file is in same dir as objfile */ |
356 | if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) { | 355 | if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) { |
357 | if (!parse_file(line, md)) { | 356 | if (!parse_file(line, md)) { |
358 | fprintf(stderr, | 357 | warn("could not open %s: %s\n", |
359 | "Warning: could not open %s: %s\n", | 358 | line, strerror(errno)); |
360 | line, strerror(errno)); | ||
361 | goto out_file; | 359 | goto out_file; |
362 | } | 360 | } |
363 | 361 | ||
@@ -383,8 +381,11 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) | |||
383 | struct md4_ctx md; | 381 | struct md4_ctx md; |
384 | char *sources, *end, *fname; | 382 | char *sources, *end, *fname; |
385 | const char *basename; | 383 | const char *basename; |
386 | char filelist[strlen(getenv("MODVERDIR")) + strlen("/") + | 384 | char filelist[PATH_MAX + 1]; |
387 | strlen(modname) - strlen(".o") + strlen(".mod") + 1 ]; | 385 | char *modverdir = getenv("MODVERDIR"); |
386 | |||
387 | if (!modverdir) | ||
388 | modverdir = "."; | ||
388 | 389 | ||
389 | /* Source files for module are in .tmp_versions/modname.mod, | 390 | /* Source files for module are in .tmp_versions/modname.mod, |
390 | after the first line. */ | 391 | after the first line. */ |
@@ -392,28 +393,25 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) | |||
392 | basename = strrchr(modname, '/') + 1; | 393 | basename = strrchr(modname, '/') + 1; |
393 | else | 394 | else |
394 | basename = modname; | 395 | basename = modname; |
395 | sprintf(filelist, "%s/%.*s.mod", getenv("MODVERDIR"), | 396 | sprintf(filelist, "%s/%.*s.mod", modverdir, |
396 | (int) strlen(basename) - 2, basename); | 397 | (int) strlen(basename) - 2, basename); |
397 | 398 | ||
398 | file = grab_file(filelist, &len); | 399 | file = grab_file(filelist, &len); |
399 | if (!file) { | 400 | if (!file) { |
400 | fprintf(stderr, "Warning: could not find versions for %s\n", | 401 | warn("could not find versions for %s\n", filelist); |
401 | filelist); | ||
402 | return; | 402 | return; |
403 | } | 403 | } |
404 | 404 | ||
405 | sources = strchr(file, '\n'); | 405 | sources = strchr(file, '\n'); |
406 | if (!sources) { | 406 | if (!sources) { |
407 | fprintf(stderr, "Warning: malformed versions file for %s\n", | 407 | warn("malformed versions file for %s\n", modname); |
408 | modname); | ||
409 | goto release; | 408 | goto release; |
410 | } | 409 | } |
411 | 410 | ||
412 | sources++; | 411 | sources++; |
413 | end = strchr(sources, '\n'); | 412 | end = strchr(sources, '\n'); |
414 | if (!end) { | 413 | if (!end) { |
415 | fprintf(stderr, "Warning: bad ending versions file for %s\n", | 414 | warn("bad ending versions file for %s\n", modname); |
416 | modname); | ||
417 | goto release; | 415 | goto release; |
418 | } | 416 | } |
419 | *end = '\0'; | 417 | *end = '\0'; |
@@ -438,19 +436,19 @@ static void write_version(const char *filename, const char *sum, | |||
438 | 436 | ||
439 | fd = open(filename, O_RDWR); | 437 | fd = open(filename, O_RDWR); |
440 | if (fd < 0) { | 438 | if (fd < 0) { |
441 | fprintf(stderr, "Warning: changing sum in %s failed: %s\n", | 439 | warn("changing sum in %s failed: %s\n", |
442 | filename, strerror(errno)); | 440 | filename, strerror(errno)); |
443 | return; | 441 | return; |
444 | } | 442 | } |
445 | 443 | ||
446 | if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { | 444 | if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { |
447 | fprintf(stderr, "Warning: changing sum in %s:%lu failed: %s\n", | 445 | warn("changing sum in %s:%lu failed: %s\n", |
448 | filename, offset, strerror(errno)); | 446 | filename, offset, strerror(errno)); |
449 | goto out; | 447 | goto out; |
450 | } | 448 | } |
451 | 449 | ||
452 | if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) { | 450 | if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) { |
453 | fprintf(stderr, "Warning: writing sum in %s failed: %s\n", | 451 | warn("writing sum in %s failed: %s\n", |
454 | filename, strerror(errno)); | 452 | filename, strerror(errno)); |
455 | goto out; | 453 | goto out; |
456 | } | 454 | } |
diff --git a/scripts/namespace.pl b/scripts/namespace.pl index 88e30e82f1ca..f34373853ef8 100644 --- a/scripts/namespace.pl +++ b/scripts/namespace.pl | |||
@@ -66,8 +66,8 @@ require 5; # at least perl 5 | |||
66 | use strict; | 66 | use strict; |
67 | use File::Find; | 67 | use File::Find; |
68 | 68 | ||
69 | my $nm = "/usr/bin/nm -p"; | 69 | my $nm = ($ENV{'NM'} || "nm") . " -p"; |
70 | my $objdump = "/usr/bin/objdump -s -j .comment"; | 70 | my $objdump = ($ENV{'OBJDUMP'} || "objdump") . " -s -j .comment"; |
71 | my $srctree = ""; | 71 | my $srctree = ""; |
72 | my $objtree = ""; | 72 | my $objtree = ""; |
73 | $srctree = "$ENV{'srctree'}/" if (exists($ENV{'srctree'})); | 73 | $srctree = "$ENV{'srctree'}/" if (exists($ENV{'srctree'})); |
diff --git a/scripts/package/Makefile b/scripts/package/Makefile index c201ef001f09..7c434e037e7f 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile | |||
@@ -32,12 +32,11 @@ MKSPEC := $(srctree)/scripts/package/mkspec | |||
32 | PREV := set -e; cd ..; | 32 | PREV := set -e; cd ..; |
33 | 33 | ||
34 | # rpm-pkg | 34 | # rpm-pkg |
35 | .PHONY: rpm-pkg rpm | 35 | # --------------------------------------------------------------------------- |
36 | |||
37 | $(objtree)/kernel.spec: $(MKSPEC) $(srctree)/Makefile | 36 | $(objtree)/kernel.spec: $(MKSPEC) $(srctree)/Makefile |
38 | $(CONFIG_SHELL) $(MKSPEC) > $@ | 37 | $(CONFIG_SHELL) $(MKSPEC) > $@ |
39 | 38 | ||
40 | rpm-pkg rpm: $(objtree)/kernel.spec | 39 | rpm-pkg rpm: $(objtree)/kernel.spec FORCE |
41 | $(MAKE) clean | 40 | $(MAKE) clean |
42 | $(PREV) ln -sf $(srctree) $(KERNELPATH) | 41 | $(PREV) ln -sf $(srctree) $(KERNELPATH) |
43 | $(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. | 42 | $(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. |
@@ -54,11 +53,11 @@ rpm-pkg rpm: $(objtree)/kernel.spec | |||
54 | clean-files := $(objtree)/kernel.spec | 53 | clean-files := $(objtree)/kernel.spec |
55 | 54 | ||
56 | # binrpm-pkg | 55 | # binrpm-pkg |
57 | .PHONY: binrpm-pkg | 56 | # --------------------------------------------------------------------------- |
58 | $(objtree)/binkernel.spec: $(MKSPEC) $(srctree)/Makefile | 57 | $(objtree)/binkernel.spec: $(MKSPEC) $(srctree)/Makefile |
59 | $(CONFIG_SHELL) $(MKSPEC) prebuilt > $@ | 58 | $(CONFIG_SHELL) $(MKSPEC) prebuilt > $@ |
60 | 59 | ||
61 | binrpm-pkg: $(objtree)/binkernel.spec | 60 | binrpm-pkg: $(objtree)/binkernel.spec FORCE |
62 | $(MAKE) KBUILD_SRC= | 61 | $(MAKE) KBUILD_SRC= |
63 | set -e; \ | 62 | set -e; \ |
64 | $(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version | 63 | $(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version |
@@ -71,9 +70,7 @@ clean-files += $(objtree)/binkernel.spec | |||
71 | 70 | ||
72 | # Deb target | 71 | # Deb target |
73 | # --------------------------------------------------------------------------- | 72 | # --------------------------------------------------------------------------- |
74 | # | 73 | deb-pkg: FORCE |
75 | .PHONY: deb-pkg | ||
76 | deb-pkg: | ||
77 | $(MAKE) KBUILD_SRC= | 74 | $(MAKE) KBUILD_SRC= |
78 | $(CONFIG_SHELL) $(srctree)/scripts/package/builddeb | 75 | $(CONFIG_SHELL) $(srctree)/scripts/package/builddeb |
79 | 76 | ||
@@ -82,8 +79,7 @@ clean-dirs += $(objtree)/debian/ | |||
82 | 79 | ||
83 | # tarball targets | 80 | # tarball targets |
84 | # --------------------------------------------------------------------------- | 81 | # --------------------------------------------------------------------------- |
85 | .PHONY: tar%pkg | 82 | tar%pkg: FORCE |
86 | tar%pkg: | ||
87 | $(MAKE) KBUILD_SRC= | 83 | $(MAKE) KBUILD_SRC= |
88 | $(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@ | 84 | $(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@ |
89 | 85 | ||
@@ -92,7 +88,7 @@ clean-dirs += $(objtree)/tar-install/ | |||
92 | 88 | ||
93 | # Help text displayed when executing 'make help' | 89 | # Help text displayed when executing 'make help' |
94 | # --------------------------------------------------------------------------- | 90 | # --------------------------------------------------------------------------- |
95 | help: | 91 | help: FORCE |
96 | @echo ' rpm-pkg - Build the kernel as an RPM package' | 92 | @echo ' rpm-pkg - Build the kernel as an RPM package' |
97 | @echo ' binrpm-pkg - Build an rpm package containing the compiled kernel' | 93 | @echo ' binrpm-pkg - Build an rpm package containing the compiled kernel' |
98 | @echo ' and modules' | 94 | @echo ' and modules' |
diff --git a/scripts/reference_discarded.pl b/scripts/reference_discarded.pl deleted file mode 100644 index 4ee6ab2135b3..000000000000 --- a/scripts/reference_discarded.pl +++ /dev/null | |||
@@ -1,112 +0,0 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | # | ||
3 | # reference_discarded.pl (C) Keith Owens 2001 <kaos@ocs.com.au> | ||
4 | # | ||
5 | # Released under GPL V2. | ||
6 | # | ||
7 | # List dangling references to vmlinux discarded sections. | ||
8 | |||
9 | use strict; | ||
10 | die($0 . " takes no arguments\n") if($#ARGV >= 0); | ||
11 | |||
12 | my %object; | ||
13 | my $object; | ||
14 | my $line; | ||
15 | my $ignore; | ||
16 | my $errorcount; | ||
17 | |||
18 | $| = 1; | ||
19 | |||
20 | # printf("Finding objects, "); | ||
21 | open(OBJDUMP_LIST, "find . -name '*.o' | xargs objdump -h |") || die "getting objdump list failed"; | ||
22 | while (defined($line = <OBJDUMP_LIST>)) { | ||
23 | chomp($line); | ||
24 | if ($line =~ /:\s+file format/) { | ||
25 | ($object = $line) =~ s/:.*//; | ||
26 | $object{$object}->{'module'} = 0; | ||
27 | $object{$object}->{'size'} = 0; | ||
28 | $object{$object}->{'off'} = 0; | ||
29 | } | ||
30 | if ($line =~ /^\s*\d+\s+\.modinfo\s+/) { | ||
31 | $object{$object}->{'module'} = 1; | ||
32 | } | ||
33 | if ($line =~ /^\s*\d+\s+\.comment\s+/) { | ||
34 | ($object{$object}->{'size'}, $object{$object}->{'off'}) = (split(' ', $line))[2,5]; | ||
35 | } | ||
36 | } | ||
37 | close(OBJDUMP_LIST); | ||
38 | # printf("%d objects, ", scalar keys(%object)); | ||
39 | $ignore = 0; | ||
40 | foreach $object (keys(%object)) { | ||
41 | if ($object{$object}->{'module'}) { | ||
42 | ++$ignore; | ||
43 | delete($object{$object}); | ||
44 | } | ||
45 | } | ||
46 | # printf("ignoring %d module(s)\n", $ignore); | ||
47 | |||
48 | # Ignore conglomerate objects, they have been built from multiple objects and we | ||
49 | # only care about the individual objects. If an object has more than one GCC: | ||
50 | # string in the comment section then it is conglomerate. This does not filter | ||
51 | # out conglomerates that consist of exactly one object, can't be helped. | ||
52 | |||
53 | # printf("Finding conglomerates, "); | ||
54 | $ignore = 0; | ||
55 | foreach $object (keys(%object)) { | ||
56 | if (exists($object{$object}->{'off'})) { | ||
57 | my ($off, $size, $comment, $l); | ||
58 | $off = hex($object{$object}->{'off'}); | ||
59 | $size = hex($object{$object}->{'size'}); | ||
60 | open(OBJECT, "<$object") || die "cannot read $object"; | ||
61 | seek(OBJECT, $off, 0) || die "seek to $off in $object failed"; | ||
62 | $l = read(OBJECT, $comment, $size); | ||
63 | die "read $size bytes from $object .comment failed" if ($l != $size); | ||
64 | close(OBJECT); | ||
65 | if ($comment =~ /GCC\:.*GCC\:/m || $object =~ /built-in\.o/) { | ||
66 | ++$ignore; | ||
67 | delete($object{$object}); | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | # printf("ignoring %d conglomerate(s)\n", $ignore); | ||
72 | |||
73 | # printf("Scanning objects\n"); | ||
74 | |||
75 | # Keith Ownes <kaos@sgi.com> commented: | ||
76 | # For our future {in}sanity, add a comment that this is the ppc .opd | ||
77 | # section, not the ia64 .opd section. | ||
78 | # ia64 .opd should not point to discarded sections. | ||
79 | $errorcount = 0; | ||
80 | foreach $object (keys(%object)) { | ||
81 | my $from; | ||
82 | open(OBJDUMP, "objdump -r $object|") || die "cannot objdump -r $object"; | ||
83 | while (defined($line = <OBJDUMP>)) { | ||
84 | chomp($line); | ||
85 | if ($line =~ /RELOCATION RECORDS FOR /) { | ||
86 | ($from = $line) =~ s/.*\[([^]]*).*/$1/; | ||
87 | } | ||
88 | if (($line =~ /\.text\.exit$/ || | ||
89 | $line =~ /\.exit\.text$/ || | ||
90 | $line =~ /\.data\.exit$/ || | ||
91 | $line =~ /\.exit\.data$/ || | ||
92 | $line =~ /\.exitcall\.exit$/) && | ||
93 | ($from !~ /\.text\.exit$/ && | ||
94 | $from !~ /\.exit\.text$/ && | ||
95 | $from !~ /\.data\.exit$/ && | ||
96 | $from !~ /\.opd$/ && | ||
97 | $from !~ /\.exit\.data$/ && | ||
98 | $from !~ /\.altinstructions$/ && | ||
99 | $from !~ /\.pdr$/ && | ||
100 | $from !~ /\.debug_.*$/ && | ||
101 | $from !~ /\.exitcall\.exit$/ && | ||
102 | $from !~ /\.eh_frame$/ && | ||
103 | $from !~ /\.stab$/)) { | ||
104 | printf("Error: %s %s refers to %s\n", $object, $from, $line); | ||
105 | $errorcount = $errorcount + 1; | ||
106 | } | ||
107 | } | ||
108 | close(OBJDUMP); | ||
109 | } | ||
110 | # printf("Done\n"); | ||
111 | |||
112 | exit(0); | ||
diff --git a/scripts/reference_init.pl b/scripts/reference_init.pl deleted file mode 100644 index 7f6960b175a2..000000000000 --- a/scripts/reference_init.pl +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | # | ||
3 | # reference_init.pl (C) Keith Owens 2002 <kaos@ocs.com.au> | ||
4 | # | ||
5 | # List references to vmlinux init sections from non-init sections. | ||
6 | |||
7 | # Unfortunately I had to exclude references from read only data to .init | ||
8 | # sections, almost all of these are false positives, they are created by | ||
9 | # gcc. The downside of excluding rodata is that there really are some | ||
10 | # user references from rodata to init code, e.g. drivers/video/vgacon.c | ||
11 | # | ||
12 | # const struct consw vga_con = { | ||
13 | # con_startup: vgacon_startup, | ||
14 | # | ||
15 | # where vgacon_startup is __init. If you want to wade through the false | ||
16 | # positives, take out the check for rodata. | ||
17 | |||
18 | use strict; | ||
19 | die($0 . " takes no arguments\n") if($#ARGV >= 0); | ||
20 | |||
21 | my %object; | ||
22 | my $object; | ||
23 | my $line; | ||
24 | my $ignore; | ||
25 | |||
26 | $| = 1; | ||
27 | |||
28 | printf("Finding objects, "); | ||
29 | open(OBJDUMP_LIST, "find . -name '*.o' | xargs objdump -h |") || die "getting objdump list failed"; | ||
30 | while (defined($line = <OBJDUMP_LIST>)) { | ||
31 | chomp($line); | ||
32 | if ($line =~ /:\s+file format/) { | ||
33 | ($object = $line) =~ s/:.*//; | ||
34 | $object{$object}->{'module'} = 0; | ||
35 | $object{$object}->{'size'} = 0; | ||
36 | $object{$object}->{'off'} = 0; | ||
37 | } | ||
38 | if ($line =~ /^\s*\d+\s+\.modinfo\s+/) { | ||
39 | $object{$object}->{'module'} = 1; | ||
40 | } | ||
41 | if ($line =~ /^\s*\d+\s+\.comment\s+/) { | ||
42 | ($object{$object}->{'size'}, $object{$object}->{'off'}) = (split(' ', $line))[2,5]; | ||
43 | } | ||
44 | } | ||
45 | close(OBJDUMP_LIST); | ||
46 | printf("%d objects, ", scalar keys(%object)); | ||
47 | $ignore = 0; | ||
48 | foreach $object (keys(%object)) { | ||
49 | if ($object{$object}->{'module'}) { | ||
50 | ++$ignore; | ||
51 | delete($object{$object}); | ||
52 | } | ||
53 | } | ||
54 | printf("ignoring %d module(s)\n", $ignore); | ||
55 | |||
56 | # Ignore conglomerate objects, they have been built from multiple objects and we | ||
57 | # only care about the individual objects. If an object has more than one GCC: | ||
58 | # string in the comment section then it is conglomerate. This does not filter | ||
59 | # out conglomerates that consist of exactly one object, can't be helped. | ||
60 | |||
61 | printf("Finding conglomerates, "); | ||
62 | $ignore = 0; | ||
63 | foreach $object (keys(%object)) { | ||
64 | if (exists($object{$object}->{'off'})) { | ||
65 | my ($off, $size, $comment, $l); | ||
66 | $off = hex($object{$object}->{'off'}); | ||
67 | $size = hex($object{$object}->{'size'}); | ||
68 | open(OBJECT, "<$object") || die "cannot read $object"; | ||
69 | seek(OBJECT, $off, 0) || die "seek to $off in $object failed"; | ||
70 | $l = read(OBJECT, $comment, $size); | ||
71 | die "read $size bytes from $object .comment failed" if ($l != $size); | ||
72 | close(OBJECT); | ||
73 | if ($comment =~ /GCC\:.*GCC\:/m || $object =~ /built-in\.o/) { | ||
74 | ++$ignore; | ||
75 | delete($object{$object}); | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | printf("ignoring %d conglomerate(s)\n", $ignore); | ||
80 | |||
81 | printf("Scanning objects\n"); | ||
82 | foreach $object (sort(keys(%object))) { | ||
83 | my $from; | ||
84 | open(OBJDUMP, "objdump -r $object|") || die "cannot objdump -r $object"; | ||
85 | while (defined($line = <OBJDUMP>)) { | ||
86 | chomp($line); | ||
87 | if ($line =~ /RELOCATION RECORDS FOR /) { | ||
88 | ($from = $line) =~ s/.*\[([^]]*).*/$1/; | ||
89 | } | ||
90 | if (($line =~ /\.init$/ || $line =~ /\.init\./) && | ||
91 | ($from !~ /\.init$/ && | ||
92 | $from !~ /\.init\./ && | ||
93 | $from !~ /\.stab$/ && | ||
94 | $from !~ /\.rodata$/ && | ||
95 | $from !~ /\.text\.lock$/ && | ||
96 | $from !~ /\.pci_fixup_header$/ && | ||
97 | $from !~ /\.pci_fixup_final$/ && | ||
98 | $from !~ /\.pdr$/ && | ||
99 | $from !~ /\__param$/ && | ||
100 | $from !~ /\.altinstructions/ && | ||
101 | $from !~ /\.eh_frame/ && | ||
102 | $from !~ /\.debug_/)) { | ||
103 | printf("Error: %s %s refers to %s\n", $object, $from, $line); | ||
104 | } | ||
105 | } | ||
106 | close(OBJDUMP); | ||
107 | } | ||
108 | printf("Done\n"); | ||