diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/.gitignore | 1 | ||||
-rw-r--r-- | scripts/Makefile | 5 | ||||
-rwxr-xr-x | scripts/checkpatch.pl | 20 | ||||
-rw-r--r-- | scripts/coccinelle/misc/ifaddr.cocci | 35 | ||||
-rw-r--r-- | scripts/coccinelle/misc/noderef.cocci | 65 | ||||
-rwxr-xr-x | scripts/config | 11 | ||||
-rwxr-xr-x | scripts/get_maintainer.pl | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | scripts/gfp-translate | 0 | ||||
-rw-r--r-- | scripts/kconfig/conf.c | 22 | ||||
-rw-r--r-- | scripts/kconfig/mconf.c | 2 | ||||
-rw-r--r-- | scripts/kconfig/nconf.c | 2 | ||||
-rw-r--r-- | scripts/link-vmlinux.sh | 221 | ||||
-rw-r--r-- | scripts/mod/file2alias.c | 9 | ||||
-rw-r--r-- | scripts/mod/modpost.c | 17 | ||||
-rw-r--r-- | scripts/package/builddeb | 2 | ||||
-rw-r--r-- | scripts/sortextable.c | 322 | ||||
-rw-r--r-- | scripts/sortextable.h | 191 |
17 files changed, 906 insertions, 22 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore index 105b21f08185..65f362d931b5 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore | |||
@@ -9,3 +9,4 @@ unifdef | |||
9 | ihex2fw | 9 | ihex2fw |
10 | recordmcount | 10 | recordmcount |
11 | docproc | 11 | docproc |
12 | sortextable | ||
diff --git a/scripts/Makefile b/scripts/Makefile index df7678febf27..a55b0067758a 100644 --- a/scripts/Makefile +++ b/scripts/Makefile | |||
@@ -8,11 +8,16 @@ | |||
8 | # conmakehash: Create arrays for initializing the kernel console tables | 8 | # conmakehash: Create arrays for initializing the kernel console tables |
9 | # docproc: Used in Documentation/DocBook | 9 | # docproc: Used in Documentation/DocBook |
10 | 10 | ||
11 | HOST_EXTRACFLAGS += -I$(srctree)/tools/include | ||
12 | |||
11 | hostprogs-$(CONFIG_KALLSYMS) += kallsyms | 13 | hostprogs-$(CONFIG_KALLSYMS) += kallsyms |
12 | hostprogs-$(CONFIG_LOGO) += pnmtologo | 14 | hostprogs-$(CONFIG_LOGO) += pnmtologo |
13 | hostprogs-$(CONFIG_VT) += conmakehash | 15 | hostprogs-$(CONFIG_VT) += conmakehash |
14 | hostprogs-$(CONFIG_IKCONFIG) += bin2c | 16 | hostprogs-$(CONFIG_IKCONFIG) += bin2c |
15 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount | 17 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount |
18 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable | ||
19 | |||
20 | HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include | ||
16 | 21 | ||
17 | always := $(hostprogs-y) $(hostprogs-m) | 22 | always := $(hostprogs-y) $(hostprogs-m) |
18 | 23 | ||
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index faea0ec612bf..e5bd60ff48e3 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl | |||
@@ -2382,6 +2382,19 @@ sub process { | |||
2382 | } | 2382 | } |
2383 | } | 2383 | } |
2384 | 2384 | ||
2385 | if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { | ||
2386 | my $orig = $1; | ||
2387 | my $level = lc($orig); | ||
2388 | $level = "warn" if ($level eq "warning"); | ||
2389 | WARN("PREFER_PR_LEVEL", | ||
2390 | "Prefer pr_$level(... to printk(KERN_$1, ...\n" . $herecurr); | ||
2391 | } | ||
2392 | |||
2393 | if ($line =~ /\bpr_warning\s*\(/) { | ||
2394 | WARN("PREFER_PR_LEVEL", | ||
2395 | "Prefer pr_warn(... to pr_warning(...\n" . $herecurr); | ||
2396 | } | ||
2397 | |||
2385 | # function brace can't be on same line, except for #defines of do while, | 2398 | # function brace can't be on same line, except for #defines of do while, |
2386 | # or if closed on same line | 2399 | # or if closed on same line |
2387 | if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and | 2400 | if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and |
@@ -2448,6 +2461,13 @@ sub process { | |||
2448 | "space prohibited between function name and open parenthesis '('\n" . $herecurr); | 2461 | "space prohibited between function name and open parenthesis '('\n" . $herecurr); |
2449 | } | 2462 | } |
2450 | } | 2463 | } |
2464 | |||
2465 | # check for whitespace before a non-naked semicolon | ||
2466 | if ($line =~ /^\+.*\S\s+;/) { | ||
2467 | CHK("SPACING", | ||
2468 | "space prohibited before semicolon\n" . $herecurr); | ||
2469 | } | ||
2470 | |||
2451 | # Check operator spacing. | 2471 | # Check operator spacing. |
2452 | if (!($line=~/\#\s*include/)) { | 2472 | if (!($line=~/\#\s*include/)) { |
2453 | my $ops = qr{ | 2473 | my $ops = qr{ |
diff --git a/scripts/coccinelle/misc/ifaddr.cocci b/scripts/coccinelle/misc/ifaddr.cocci new file mode 100644 index 000000000000..3e4089a77000 --- /dev/null +++ b/scripts/coccinelle/misc/ifaddr.cocci | |||
@@ -0,0 +1,35 @@ | |||
1 | /// the address of a variable or field is non-zero is likely always to bo | ||
2 | /// non-zero | ||
3 | /// | ||
4 | // Confidence: High | ||
5 | // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. | ||
6 | // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. | ||
7 | // URL: http://coccinelle.lip6.fr/ | ||
8 | // Comments: | ||
9 | // Options: -no_includes -include_headers | ||
10 | |||
11 | virtual org | ||
12 | virtual report | ||
13 | virtual context | ||
14 | |||
15 | @r@ | ||
16 | expression x; | ||
17 | statement S1,S2; | ||
18 | position p; | ||
19 | @@ | ||
20 | |||
21 | *if@p (&x) | ||
22 | S1 else S2 | ||
23 | |||
24 | @script:python depends on org@ | ||
25 | p << r.p; | ||
26 | @@ | ||
27 | |||
28 | cocci.print_main("test of a variable/field address",p) | ||
29 | |||
30 | @script:python depends on report@ | ||
31 | p << r.p; | ||
32 | @@ | ||
33 | |||
34 | msg = "ERROR: test of a variable/field address" | ||
35 | coccilib.report.print_report(p[0],msg) | ||
diff --git a/scripts/coccinelle/misc/noderef.cocci b/scripts/coccinelle/misc/noderef.cocci new file mode 100644 index 000000000000..c1707214e602 --- /dev/null +++ b/scripts/coccinelle/misc/noderef.cocci | |||
@@ -0,0 +1,65 @@ | |||
1 | /// sizeof when applied to a pointer typed expression gives the size of | ||
2 | /// the pointer | ||
3 | /// | ||
4 | // Confidence: High | ||
5 | // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. | ||
6 | // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. | ||
7 | // URL: http://coccinelle.lip6.fr/ | ||
8 | // Comments: | ||
9 | // Options: -no_includes -include_headers | ||
10 | |||
11 | virtual org | ||
12 | virtual report | ||
13 | virtual context | ||
14 | virtual patch | ||
15 | |||
16 | @depends on patch@ | ||
17 | expression *x; | ||
18 | expression f; | ||
19 | type T; | ||
20 | @@ | ||
21 | |||
22 | ( | ||
23 | x = <+... sizeof( | ||
24 | - x | ||
25 | + *x | ||
26 | ) ...+> | ||
27 | | | ||
28 | f(...,(T)(x),...,sizeof( | ||
29 | - x | ||
30 | + *x | ||
31 | ),...) | ||
32 | | | ||
33 | f(...,sizeof(x),...,(T)( | ||
34 | - x | ||
35 | + *x | ||
36 | ),...) | ||
37 | ) | ||
38 | |||
39 | @r depends on !patch@ | ||
40 | expression *x; | ||
41 | expression f; | ||
42 | position p; | ||
43 | type T; | ||
44 | @@ | ||
45 | |||
46 | ( | ||
47 | *x = <+... sizeof@p(x) ...+> | ||
48 | | | ||
49 | *f(...,(T)(x),...,sizeof@p(x),...) | ||
50 | | | ||
51 | *f(...,sizeof@p(x),...,(T)(x),...) | ||
52 | ) | ||
53 | |||
54 | @script:python depends on org@ | ||
55 | p << r.p; | ||
56 | @@ | ||
57 | |||
58 | cocci.print_main("application of sizeof to pointer",p) | ||
59 | |||
60 | @script:python depends on report@ | ||
61 | p << r.p; | ||
62 | @@ | ||
63 | |||
64 | msg = "ERROR: application of sizeof to pointer" | ||
65 | coccilib.report.print_report(p[0],msg) | ||
diff --git a/scripts/config b/scripts/config index a7c7c4b8e957..ed6653ef9702 100755 --- a/scripts/config +++ b/scripts/config | |||
@@ -107,7 +107,8 @@ while [ "$1" != "" ] ; do | |||
107 | ;; | 107 | ;; |
108 | 108 | ||
109 | --set-str) | 109 | --set-str) |
110 | set_var "CONFIG_$ARG" "CONFIG_$ARG=\"$1\"" | 110 | # sed swallows one level of escaping, so we need double-escaping |
111 | set_var "CONFIG_$ARG" "CONFIG_$ARG=\"${1//\"/\\\\\"}\"" | ||
111 | shift | 112 | shift |
112 | ;; | 113 | ;; |
113 | 114 | ||
@@ -124,9 +125,11 @@ while [ "$1" != "" ] ; do | |||
124 | if [ $? != 0 ] ; then | 125 | if [ $? != 0 ] ; then |
125 | echo undef | 126 | echo undef |
126 | else | 127 | else |
127 | V="${V/CONFIG_$ARG=/}" | 128 | V="${V/#CONFIG_$ARG=/}" |
128 | V="${V/\"/}" | 129 | V="${V/#\"/}" |
129 | echo "$V" | 130 | V="${V/%\"/}" |
131 | V="${V/\\\"/\"}" | ||
132 | echo "${V}" | ||
130 | fi | 133 | fi |
131 | fi | 134 | fi |
132 | ;; | 135 | ;; |
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 0948c6b5a321..8b673dd4627f 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl | |||
@@ -83,6 +83,8 @@ push(@signature_tags, "Signed-off-by:"); | |||
83 | push(@signature_tags, "Reviewed-by:"); | 83 | push(@signature_tags, "Reviewed-by:"); |
84 | push(@signature_tags, "Acked-by:"); | 84 | push(@signature_tags, "Acked-by:"); |
85 | 85 | ||
86 | my $signature_pattern = "\(" . join("|", @signature_tags) . "\)"; | ||
87 | |||
86 | # rfc822 email address - preloaded methods go here. | 88 | # rfc822 email address - preloaded methods go here. |
87 | my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; | 89 | my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; |
88 | my $rfc822_char = '[\\000-\\377]'; | 90 | my $rfc822_char = '[\\000-\\377]'; |
@@ -473,7 +475,6 @@ my @subsystem = (); | |||
473 | my @status = (); | 475 | my @status = (); |
474 | my %deduplicate_name_hash = (); | 476 | my %deduplicate_name_hash = (); |
475 | my %deduplicate_address_hash = (); | 477 | my %deduplicate_address_hash = (); |
476 | my $signature_pattern; | ||
477 | 478 | ||
478 | my @maintainers = get_maintainers(); | 479 | my @maintainers = get_maintainers(); |
479 | 480 | ||
diff --git a/scripts/gfp-translate b/scripts/gfp-translate index c9230e158a8f..c9230e158a8f 100644..100755 --- a/scripts/gfp-translate +++ b/scripts/gfp-translate | |||
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index f208f900ed3a..0dc4a2c779b1 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c | |||
@@ -574,8 +574,15 @@ int main(int ac, char **av) | |||
574 | case alldefconfig: | 574 | case alldefconfig: |
575 | case randconfig: | 575 | case randconfig: |
576 | name = getenv("KCONFIG_ALLCONFIG"); | 576 | name = getenv("KCONFIG_ALLCONFIG"); |
577 | if (name && !stat(name, &tmpstat)) { | 577 | if (!name) |
578 | conf_read_simple(name, S_DEF_USER); | 578 | break; |
579 | if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { | ||
580 | if (conf_read_simple(name, S_DEF_USER)) { | ||
581 | fprintf(stderr, | ||
582 | _("*** Can't read seed configuration \"%s\"!\n"), | ||
583 | name); | ||
584 | exit(1); | ||
585 | } | ||
579 | break; | 586 | break; |
580 | } | 587 | } |
581 | switch (input_mode) { | 588 | switch (input_mode) { |
@@ -586,10 +593,13 @@ int main(int ac, char **av) | |||
586 | case randconfig: name = "allrandom.config"; break; | 593 | case randconfig: name = "allrandom.config"; break; |
587 | default: break; | 594 | default: break; |
588 | } | 595 | } |
589 | if (!stat(name, &tmpstat)) | 596 | if (conf_read_simple(name, S_DEF_USER) && |
590 | conf_read_simple(name, S_DEF_USER); | 597 | conf_read_simple("all.config", S_DEF_USER)) { |
591 | else if (!stat("all.config", &tmpstat)) | 598 | fprintf(stderr, |
592 | conf_read_simple("all.config", S_DEF_USER); | 599 | _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), |
600 | name); | ||
601 | exit(1); | ||
602 | } | ||
593 | break; | 603 | break; |
594 | default: | 604 | default: |
595 | break; | 605 | break; |
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 2c6286c0bc1a..f606738d421d 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c | |||
@@ -240,7 +240,7 @@ search_help[] = N_( | |||
240 | "Defined at drivers/pci/Kconfig:47\n" | 240 | "Defined at drivers/pci/Kconfig:47\n" |
241 | "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" | 241 | "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" |
242 | "Location:\n" | 242 | "Location:\n" |
243 | " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" | 243 | " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" |
244 | " -> PCI support (PCI [=y])\n" | 244 | " -> PCI support (PCI [=y])\n" |
245 | " -> PCI access mode (<choice> [=y])\n" | 245 | " -> PCI access mode (<choice> [=y])\n" |
246 | "Selects: LIBCRC32\n" | 246 | "Selects: LIBCRC32\n" |
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 73070cb0b6de..8c0eb65978c9 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c | |||
@@ -223,7 +223,7 @@ search_help[] = N_( | |||
223 | "Defined at drivers/pci/Kconfig:47\n" | 223 | "Defined at drivers/pci/Kconfig:47\n" |
224 | "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" | 224 | "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" |
225 | "Location:\n" | 225 | "Location:\n" |
226 | " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" | 226 | " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" |
227 | " -> PCI support (PCI [ = y])\n" | 227 | " -> PCI support (PCI [ = y])\n" |
228 | " -> PCI access mode (<choice> [ = y])\n" | 228 | " -> PCI access mode (<choice> [ = y])\n" |
229 | "Selects: LIBCRC32\n" | 229 | "Selects: LIBCRC32\n" |
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh new file mode 100644 index 000000000000..cd9c6c6bb4c9 --- /dev/null +++ b/scripts/link-vmlinux.sh | |||
@@ -0,0 +1,221 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # link vmlinux | ||
4 | # | ||
5 | # vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_INIT) and | ||
6 | # $(KBUILD_VMLINUX_MAIN). Most are built-in.o files from top-level directories | ||
7 | # in the kernel tree, others are specified in arch/$(ARCH)/Makefile. | ||
8 | # Ordering when linking is important, and $(KBUILD_VMLINUX_INIT) must be first. | ||
9 | # | ||
10 | # vmlinux | ||
11 | # ^ | ||
12 | # | | ||
13 | # +-< $(KBUILD_VMLINUX_INIT) | ||
14 | # | +--< init/version.o + more | ||
15 | # | | ||
16 | # +--< $(KBUILD_VMLINUX_MAIN) | ||
17 | # | +--< drivers/built-in.o mm/built-in.o + more | ||
18 | # | | ||
19 | # +-< ${kallsymso} (see description in KALLSYMS section) | ||
20 | # | ||
21 | # vmlinux version (uname -v) cannot be updated during normal | ||
22 | # descending-into-subdirs phase since we do not yet know if we need to | ||
23 | # update vmlinux. | ||
24 | # Therefore this step is delayed until just before final link of vmlinux. | ||
25 | # | ||
26 | # System.map is generated to document addresses of all kernel symbols | ||
27 | |||
28 | # Error out on error | ||
29 | set -e | ||
30 | |||
31 | # Nice output in kbuild format | ||
32 | # Will be supressed by "make -s" | ||
33 | info() | ||
34 | { | ||
35 | if [ "${quiet}" != "silent_" ]; then | ||
36 | printf " %-7s %s\n" ${1} ${2} | ||
37 | fi | ||
38 | } | ||
39 | |||
40 | # Link of vmlinux.o used for section mismatch analysis | ||
41 | # ${1} output file | ||
42 | modpost_link() | ||
43 | { | ||
44 | ${LD} ${LDFLAGS} -r -o ${1} ${KBUILD_VMLINUX_INIT} \ | ||
45 | --start-group ${KBUILD_VMLINUX_MAIN} --end-group | ||
46 | } | ||
47 | |||
48 | # Link of vmlinux | ||
49 | # ${1} - optional extra .o files | ||
50 | # ${2} - output file | ||
51 | vmlinux_link() | ||
52 | { | ||
53 | local lds="${objtree}/${KBUILD_LDS}" | ||
54 | |||
55 | if [ "${SRCARCH}" != "um" ]; then | ||
56 | ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ | ||
57 | -T ${lds} ${KBUILD_VMLINUX_INIT} \ | ||
58 | --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1} | ||
59 | else | ||
60 | ${CC} ${CFLAGS_vmlinux} -o ${2} \ | ||
61 | -Wl,-T,${lds} ${KBUILD_VMLINUX_INIT} \ | ||
62 | -Wl,--start-group \ | ||
63 | ${KBUILD_VMLINUX_MAIN} \ | ||
64 | -Wl,--end-group \ | ||
65 | -lutil ${1} | ||
66 | rm -f linux | ||
67 | fi | ||
68 | } | ||
69 | |||
70 | |||
71 | # Create ${2} .o file with all symbols from the ${1} object file | ||
72 | kallsyms() | ||
73 | { | ||
74 | info KSYM ${2} | ||
75 | local kallsymopt; | ||
76 | |||
77 | if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then | ||
78 | kallsymopt=--all-symbols | ||
79 | fi | ||
80 | |||
81 | local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ | ||
82 | ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" | ||
83 | |||
84 | ${NM} -n ${1} | \ | ||
85 | scripts/kallsyms ${kallsymopt} | \ | ||
86 | ${CC} ${aflags} -c -o ${2} -x assembler-with-cpp - | ||
87 | } | ||
88 | |||
89 | # Create map file with all symbols from ${1} | ||
90 | # See mksymap for additional details | ||
91 | mksysmap() | ||
92 | { | ||
93 | ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2} | ||
94 | } | ||
95 | |||
96 | sortextable() | ||
97 | { | ||
98 | ${objtree}/scripts/sortextable ${1} | ||
99 | } | ||
100 | |||
101 | # Delete output files in case of error | ||
102 | trap cleanup SIGHUP SIGINT SIGQUIT SIGTERM ERR | ||
103 | cleanup() | ||
104 | { | ||
105 | rm -f .old_version | ||
106 | rm -f .tmp_System.map | ||
107 | rm -f .tmp_kallsyms* | ||
108 | rm -f .tmp_version | ||
109 | rm -f .tmp_vmlinux* | ||
110 | rm -f System.map | ||
111 | rm -f vmlinux | ||
112 | rm -f vmlinux.o | ||
113 | } | ||
114 | |||
115 | # | ||
116 | # | ||
117 | # Use "make V=1" to debug this script | ||
118 | case "${KBUILD_VERBOSE}" in | ||
119 | *1*) | ||
120 | set -x | ||
121 | ;; | ||
122 | esac | ||
123 | |||
124 | if [ "$1" = "clean" ]; then | ||
125 | cleanup | ||
126 | exit 0 | ||
127 | fi | ||
128 | |||
129 | # We need access to CONFIG_ symbols | ||
130 | . ./.config | ||
131 | |||
132 | #link vmlinux.o | ||
133 | info LD vmlinux.o | ||
134 | modpost_link vmlinux.o | ||
135 | |||
136 | # modpost vmlinux.o to check for section mismatches | ||
137 | ${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o | ||
138 | |||
139 | # Update version | ||
140 | info GEN .version | ||
141 | if [ ! -r .version ]; then | ||
142 | rm -f .version; | ||
143 | echo 1 >.version; | ||
144 | else | ||
145 | mv .version .old_version; | ||
146 | expr 0$(cat .old_version) + 1 >.version; | ||
147 | fi; | ||
148 | |||
149 | # final build of init/ | ||
150 | ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init | ||
151 | |||
152 | kallsymso="" | ||
153 | kallsyms_vmlinux="" | ||
154 | if [ -n "${CONFIG_KALLSYMS}" ]; then | ||
155 | |||
156 | # kallsyms support | ||
157 | # Generate section listing all symbols and add it into vmlinux | ||
158 | # It's a three step process: | ||
159 | # 1) Link .tmp_vmlinux1 so it has all symbols and sections, | ||
160 | # but __kallsyms is empty. | ||
161 | # Running kallsyms on that gives us .tmp_kallsyms1.o with | ||
162 | # the right size | ||
163 | # 2) Link .tmp_vmlinux2 so it now has a __kallsyms section of | ||
164 | # the right size, but due to the added section, some | ||
165 | # addresses have shifted. | ||
166 | # From here, we generate a correct .tmp_kallsyms2.o | ||
167 | # 2a) We may use an extra pass as this has been necessary to | ||
168 | # woraround some alignment related bugs. | ||
169 | # KALLSYMS_EXTRA_PASS=1 is used to trigger this. | ||
170 | # 3) The correct ${kallsymso} is linked into the final vmlinux. | ||
171 | # | ||
172 | # a) Verify that the System.map from vmlinux matches the map from | ||
173 | # ${kallsymso}. | ||
174 | |||
175 | kallsymso=.tmp_kallsyms2.o | ||
176 | kallsyms_vmlinux=.tmp_vmlinux2 | ||
177 | |||
178 | # step 1 | ||
179 | vmlinux_link "" .tmp_vmlinux1 | ||
180 | kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o | ||
181 | |||
182 | # step 2 | ||
183 | vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2 | ||
184 | kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o | ||
185 | |||
186 | # step 2a | ||
187 | if [ -n "${KALLSYMS_EXTRA_PASS}" ]; then | ||
188 | kallsymso=.tmp_kallsyms3.o | ||
189 | kallsyms_vmlinux=.tmp_vmlinux3 | ||
190 | |||
191 | vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3 | ||
192 | |||
193 | kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o | ||
194 | fi | ||
195 | fi | ||
196 | |||
197 | info LD vmlinux | ||
198 | vmlinux_link "${kallsymso}" vmlinux | ||
199 | |||
200 | if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then | ||
201 | info SORTEX vmlinux | ||
202 | sortextable vmlinux | ||
203 | fi | ||
204 | |||
205 | info SYSMAP System.map | ||
206 | mksysmap vmlinux System.map | ||
207 | |||
208 | # step a (see comment above) | ||
209 | if [ -n "${CONFIG_KALLSYMS}" ]; then | ||
210 | mksysmap ${kallsyms_vmlinux} .tmp_System.map | ||
211 | |||
212 | if ! cmp -s System.map .tmp_System.map; then | ||
213 | echo Inconsistent kallsyms data | ||
214 | echo echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround | ||
215 | cleanup | ||
216 | exit 1 | ||
217 | fi | ||
218 | fi | ||
219 | |||
220 | # We made a new kernel - delete old version file | ||
221 | rm -f .old_version | ||
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 8e730ccc3f2b..5759751a1f61 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -336,10 +336,13 @@ static int do_hid_entry(const char *filename, | |||
336 | struct hid_device_id *id, char *alias) | 336 | struct hid_device_id *id, char *alias) |
337 | { | 337 | { |
338 | id->bus = TO_NATIVE(id->bus); | 338 | id->bus = TO_NATIVE(id->bus); |
339 | id->group = TO_NATIVE(id->group); | ||
339 | id->vendor = TO_NATIVE(id->vendor); | 340 | id->vendor = TO_NATIVE(id->vendor); |
340 | id->product = TO_NATIVE(id->product); | 341 | id->product = TO_NATIVE(id->product); |
341 | 342 | ||
342 | sprintf(alias, "hid:b%04X", id->bus); | 343 | sprintf(alias, "hid:"); |
344 | ADD(alias, "b", id->bus != HID_BUS_ANY, id->bus); | ||
345 | ADD(alias, "g", id->group != HID_GROUP_ANY, id->group); | ||
343 | ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor); | 346 | ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor); |
344 | ADD(alias, "p", id->product != HID_ANY_ID, id->product); | 347 | ADD(alias, "p", id->product != HID_ANY_ID, id->product); |
345 | 348 | ||
@@ -1100,6 +1103,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
1100 | if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) | 1103 | if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) |
1101 | return; | 1104 | return; |
1102 | 1105 | ||
1106 | /* We're looking for an object */ | ||
1107 | if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) | ||
1108 | return; | ||
1109 | |||
1103 | /* All our symbols are of form <prefix>__mod_XXX_device_table. */ | 1110 | /* All our symbols are of form <prefix>__mod_XXX_device_table. */ |
1104 | name = strstr(symname, "__mod_"); | 1111 | name = strstr(symname, "__mod_"); |
1105 | if (!name) | 1112 | if (!name) |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index c4e7d1510f9d..0f84bb38eb0d 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -337,17 +337,20 @@ static void sym_update_crc(const char *name, struct module *mod, | |||
337 | void *grab_file(const char *filename, unsigned long *size) | 337 | void *grab_file(const char *filename, unsigned long *size) |
338 | { | 338 | { |
339 | struct stat st; | 339 | struct stat st; |
340 | void *map; | 340 | void *map = MAP_FAILED; |
341 | int fd; | 341 | int fd; |
342 | 342 | ||
343 | fd = open(filename, O_RDONLY); | 343 | fd = open(filename, O_RDONLY); |
344 | if (fd < 0 || fstat(fd, &st) != 0) | 344 | if (fd < 0) |
345 | return NULL; | 345 | return NULL; |
346 | if (fstat(fd, &st)) | ||
347 | goto failed; | ||
346 | 348 | ||
347 | *size = st.st_size; | 349 | *size = st.st_size; |
348 | map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); | 350 | map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); |
349 | close(fd); | ||
350 | 351 | ||
352 | failed: | ||
353 | close(fd); | ||
351 | if (map == MAP_FAILED) | 354 | if (map == MAP_FAILED) |
352 | return NULL; | 355 | return NULL; |
353 | return map; | 356 | return map; |
@@ -1850,14 +1853,14 @@ static void add_header(struct buffer *b, struct module *mod) | |||
1850 | buf_printf(b, "\n"); | 1853 | buf_printf(b, "\n"); |
1851 | buf_printf(b, "struct module __this_module\n"); | 1854 | buf_printf(b, "struct module __this_module\n"); |
1852 | buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); | 1855 | buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); |
1853 | buf_printf(b, " .name = KBUILD_MODNAME,\n"); | 1856 | buf_printf(b, "\t.name = KBUILD_MODNAME,\n"); |
1854 | if (mod->has_init) | 1857 | if (mod->has_init) |
1855 | buf_printf(b, " .init = init_module,\n"); | 1858 | buf_printf(b, "\t.init = init_module,\n"); |
1856 | if (mod->has_cleanup) | 1859 | if (mod->has_cleanup) |
1857 | buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n" | 1860 | buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n" |
1858 | " .exit = cleanup_module,\n" | 1861 | "\t.exit = cleanup_module,\n" |
1859 | "#endif\n"); | 1862 | "#endif\n"); |
1860 | buf_printf(b, " .arch = MODULE_ARCH_INIT,\n"); | 1863 | buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n"); |
1861 | buf_printf(b, "};\n"); | 1864 | buf_printf(b, "};\n"); |
1862 | } | 1865 | } |
1863 | 1866 | ||
diff --git a/scripts/package/builddeb b/scripts/package/builddeb index eee5f8ed2493..c95fdda58414 100644 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb | |||
@@ -245,7 +245,7 @@ fi | |||
245 | # Build header package | 245 | # Build header package |
246 | (cd $srctree; find . -name Makefile -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles") | 246 | (cd $srctree; find . -name Makefile -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles") |
247 | (cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles") | 247 | (cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles") |
248 | (cd $objtree; find .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles") | 248 | (cd $objtree; find arch/$SRCARCH/include .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles") |
249 | destdir=$kernel_headers_dir/usr/src/linux-headers-$version | 249 | destdir=$kernel_headers_dir/usr/src/linux-headers-$version |
250 | mkdir -p "$destdir" | 250 | mkdir -p "$destdir" |
251 | (cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -) | 251 | (cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -) |
diff --git a/scripts/sortextable.c b/scripts/sortextable.c new file mode 100644 index 000000000000..1ca9ceb95eb6 --- /dev/null +++ b/scripts/sortextable.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | * sortextable.c: Sort the kernel's exception table | ||
3 | * | ||
4 | * Copyright 2011 - 2012 Cavium, Inc. | ||
5 | * | ||
6 | * Based on code taken from recortmcount.c which is: | ||
7 | * | ||
8 | * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. | ||
9 | * Licensed under the GNU General Public License, version 2 (GPLv2). | ||
10 | * | ||
11 | * Restructured to fit Linux format, as well as other updates: | ||
12 | * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. | ||
13 | */ | ||
14 | |||
15 | /* | ||
16 | * Strategy: alter the vmlinux file in-place. | ||
17 | */ | ||
18 | |||
19 | #include <sys/types.h> | ||
20 | #include <sys/mman.h> | ||
21 | #include <sys/stat.h> | ||
22 | #include <getopt.h> | ||
23 | #include <elf.h> | ||
24 | #include <fcntl.h> | ||
25 | #include <setjmp.h> | ||
26 | #include <stdio.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <string.h> | ||
29 | #include <unistd.h> | ||
30 | |||
31 | #include <tools/be_byteshift.h> | ||
32 | #include <tools/le_byteshift.h> | ||
33 | |||
34 | static int fd_map; /* File descriptor for file being modified. */ | ||
35 | static int mmap_failed; /* Boolean flag. */ | ||
36 | static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */ | ||
37 | static struct stat sb; /* Remember .st_size, etc. */ | ||
38 | static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */ | ||
39 | |||
40 | /* setjmp() return values */ | ||
41 | enum { | ||
42 | SJ_SETJMP = 0, /* hardwired first return */ | ||
43 | SJ_FAIL, | ||
44 | SJ_SUCCEED | ||
45 | }; | ||
46 | |||
47 | /* Per-file resource cleanup when multiple files. */ | ||
48 | static void | ||
49 | cleanup(void) | ||
50 | { | ||
51 | if (!mmap_failed) | ||
52 | munmap(ehdr_curr, sb.st_size); | ||
53 | close(fd_map); | ||
54 | } | ||
55 | |||
56 | static void __attribute__((noreturn)) | ||
57 | fail_file(void) | ||
58 | { | ||
59 | cleanup(); | ||
60 | longjmp(jmpenv, SJ_FAIL); | ||
61 | } | ||
62 | |||
63 | static void __attribute__((noreturn)) | ||
64 | succeed_file(void) | ||
65 | { | ||
66 | cleanup(); | ||
67 | longjmp(jmpenv, SJ_SUCCEED); | ||
68 | } | ||
69 | |||
70 | |||
71 | /* | ||
72 | * Get the whole file as a programming convenience in order to avoid | ||
73 | * malloc+lseek+read+free of many pieces. If successful, then mmap | ||
74 | * avoids copying unused pieces; else just read the whole file. | ||
75 | * Open for both read and write. | ||
76 | */ | ||
77 | static void *mmap_file(char const *fname) | ||
78 | { | ||
79 | void *addr; | ||
80 | |||
81 | fd_map = open(fname, O_RDWR); | ||
82 | if (fd_map < 0 || fstat(fd_map, &sb) < 0) { | ||
83 | perror(fname); | ||
84 | fail_file(); | ||
85 | } | ||
86 | if (!S_ISREG(sb.st_mode)) { | ||
87 | fprintf(stderr, "not a regular file: %s\n", fname); | ||
88 | fail_file(); | ||
89 | } | ||
90 | addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, | ||
91 | fd_map, 0); | ||
92 | if (addr == MAP_FAILED) { | ||
93 | mmap_failed = 1; | ||
94 | fprintf(stderr, "Could not mmap file: %s\n", fname); | ||
95 | fail_file(); | ||
96 | } | ||
97 | return addr; | ||
98 | } | ||
99 | |||
100 | static uint64_t r8be(const uint64_t *x) | ||
101 | { | ||
102 | return get_unaligned_be64(x); | ||
103 | } | ||
104 | static uint32_t rbe(const uint32_t *x) | ||
105 | { | ||
106 | return get_unaligned_be32(x); | ||
107 | } | ||
108 | static uint16_t r2be(const uint16_t *x) | ||
109 | { | ||
110 | return get_unaligned_be16(x); | ||
111 | } | ||
112 | static uint64_t r8le(const uint64_t *x) | ||
113 | { | ||
114 | return get_unaligned_le64(x); | ||
115 | } | ||
116 | static uint32_t rle(const uint32_t *x) | ||
117 | { | ||
118 | return get_unaligned_le32(x); | ||
119 | } | ||
120 | static uint16_t r2le(const uint16_t *x) | ||
121 | { | ||
122 | return get_unaligned_le16(x); | ||
123 | } | ||
124 | |||
125 | static void w8be(uint64_t val, uint64_t *x) | ||
126 | { | ||
127 | put_unaligned_be64(val, x); | ||
128 | } | ||
129 | static void wbe(uint32_t val, uint32_t *x) | ||
130 | { | ||
131 | put_unaligned_be32(val, x); | ||
132 | } | ||
133 | static void w2be(uint16_t val, uint16_t *x) | ||
134 | { | ||
135 | put_unaligned_be16(val, x); | ||
136 | } | ||
137 | static void w8le(uint64_t val, uint64_t *x) | ||
138 | { | ||
139 | put_unaligned_le64(val, x); | ||
140 | } | ||
141 | static void wle(uint32_t val, uint32_t *x) | ||
142 | { | ||
143 | put_unaligned_le32(val, x); | ||
144 | } | ||
145 | static void w2le(uint16_t val, uint16_t *x) | ||
146 | { | ||
147 | put_unaligned_le16(val, x); | ||
148 | } | ||
149 | |||
150 | static uint64_t (*r8)(const uint64_t *); | ||
151 | static uint32_t (*r)(const uint32_t *); | ||
152 | static uint16_t (*r2)(const uint16_t *); | ||
153 | static void (*w8)(uint64_t, uint64_t *); | ||
154 | static void (*w)(uint32_t, uint32_t *); | ||
155 | static void (*w2)(uint16_t, uint16_t *); | ||
156 | |||
157 | typedef void (*table_sort_t)(char *, int); | ||
158 | |||
159 | /* 32 bit and 64 bit are very similar */ | ||
160 | #include "sortextable.h" | ||
161 | #define SORTEXTABLE_64 | ||
162 | #include "sortextable.h" | ||
163 | |||
164 | static int compare_x86_table(const void *a, const void *b) | ||
165 | { | ||
166 | int32_t av = (int32_t)r(a); | ||
167 | int32_t bv = (int32_t)r(b); | ||
168 | |||
169 | if (av < bv) | ||
170 | return -1; | ||
171 | if (av > bv) | ||
172 | return 1; | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static void sort_x86_table(char *extab_image, int image_size) | ||
177 | { | ||
178 | int i; | ||
179 | |||
180 | /* | ||
181 | * Do the same thing the runtime sort does, first normalize to | ||
182 | * being relative to the start of the section. | ||
183 | */ | ||
184 | i = 0; | ||
185 | while (i < image_size) { | ||
186 | uint32_t *loc = (uint32_t *)(extab_image + i); | ||
187 | w(r(loc) + i, loc); | ||
188 | i += 4; | ||
189 | } | ||
190 | |||
191 | qsort(extab_image, image_size / 8, 8, compare_x86_table); | ||
192 | |||
193 | /* Now denormalize. */ | ||
194 | i = 0; | ||
195 | while (i < image_size) { | ||
196 | uint32_t *loc = (uint32_t *)(extab_image + i); | ||
197 | w(r(loc) - i, loc); | ||
198 | i += 4; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | static void | ||
203 | do_file(char const *const fname) | ||
204 | { | ||
205 | table_sort_t custom_sort; | ||
206 | Elf32_Ehdr *ehdr = mmap_file(fname); | ||
207 | |||
208 | ehdr_curr = ehdr; | ||
209 | switch (ehdr->e_ident[EI_DATA]) { | ||
210 | default: | ||
211 | fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", | ||
212 | ehdr->e_ident[EI_DATA], fname); | ||
213 | fail_file(); | ||
214 | break; | ||
215 | case ELFDATA2LSB: | ||
216 | r = rle; | ||
217 | r2 = r2le; | ||
218 | r8 = r8le; | ||
219 | w = wle; | ||
220 | w2 = w2le; | ||
221 | w8 = w8le; | ||
222 | break; | ||
223 | case ELFDATA2MSB: | ||
224 | r = rbe; | ||
225 | r2 = r2be; | ||
226 | r8 = r8be; | ||
227 | w = wbe; | ||
228 | w2 = w2be; | ||
229 | w8 = w8be; | ||
230 | break; | ||
231 | } /* end switch */ | ||
232 | if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 | ||
233 | || r2(&ehdr->e_type) != ET_EXEC | ||
234 | || ehdr->e_ident[EI_VERSION] != EV_CURRENT) { | ||
235 | fprintf(stderr, "unrecognized ET_EXEC file %s\n", fname); | ||
236 | fail_file(); | ||
237 | } | ||
238 | |||
239 | custom_sort = NULL; | ||
240 | switch (r2(&ehdr->e_machine)) { | ||
241 | default: | ||
242 | fprintf(stderr, "unrecognized e_machine %d %s\n", | ||
243 | r2(&ehdr->e_machine), fname); | ||
244 | fail_file(); | ||
245 | break; | ||
246 | case EM_386: | ||
247 | case EM_X86_64: | ||
248 | custom_sort = sort_x86_table; | ||
249 | break; | ||
250 | case EM_MIPS: | ||
251 | break; | ||
252 | } /* end switch */ | ||
253 | |||
254 | switch (ehdr->e_ident[EI_CLASS]) { | ||
255 | default: | ||
256 | fprintf(stderr, "unrecognized ELF class %d %s\n", | ||
257 | ehdr->e_ident[EI_CLASS], fname); | ||
258 | fail_file(); | ||
259 | break; | ||
260 | case ELFCLASS32: | ||
261 | if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) | ||
262 | || r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { | ||
263 | fprintf(stderr, | ||
264 | "unrecognized ET_EXEC file: %s\n", fname); | ||
265 | fail_file(); | ||
266 | } | ||
267 | do32(ehdr, fname, custom_sort); | ||
268 | break; | ||
269 | case ELFCLASS64: { | ||
270 | Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr; | ||
271 | if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) | ||
272 | || r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { | ||
273 | fprintf(stderr, | ||
274 | "unrecognized ET_EXEC file: %s\n", fname); | ||
275 | fail_file(); | ||
276 | } | ||
277 | do64(ghdr, fname, custom_sort); | ||
278 | break; | ||
279 | } | ||
280 | } /* end switch */ | ||
281 | |||
282 | cleanup(); | ||
283 | } | ||
284 | |||
285 | int | ||
286 | main(int argc, char *argv[]) | ||
287 | { | ||
288 | int n_error = 0; /* gcc-4.3.0 false positive complaint */ | ||
289 | int i; | ||
290 | |||
291 | if (argc < 2) { | ||
292 | fprintf(stderr, "usage: sortextable vmlinux...\n"); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | /* Process each file in turn, allowing deep failure. */ | ||
297 | for (i = 1; i < argc; i++) { | ||
298 | char *file = argv[i]; | ||
299 | int const sjval = setjmp(jmpenv); | ||
300 | |||
301 | switch (sjval) { | ||
302 | default: | ||
303 | fprintf(stderr, "internal error: %s\n", file); | ||
304 | exit(1); | ||
305 | break; | ||
306 | case SJ_SETJMP: /* normal sequence */ | ||
307 | /* Avoid problems if early cleanup() */ | ||
308 | fd_map = -1; | ||
309 | ehdr_curr = NULL; | ||
310 | mmap_failed = 1; | ||
311 | do_file(file); | ||
312 | break; | ||
313 | case SJ_FAIL: /* error in do_file or below */ | ||
314 | ++n_error; | ||
315 | break; | ||
316 | case SJ_SUCCEED: /* premature success */ | ||
317 | /* do nothing */ | ||
318 | break; | ||
319 | } /* end switch */ | ||
320 | } | ||
321 | return !!n_error; | ||
322 | } | ||
diff --git a/scripts/sortextable.h b/scripts/sortextable.h new file mode 100644 index 000000000000..e4fd45b7e456 --- /dev/null +++ b/scripts/sortextable.h | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * sortextable.h | ||
3 | * | ||
4 | * Copyright 2011 - 2012 Cavium, Inc. | ||
5 | * | ||
6 | * Some of this code was taken out of recordmcount.h written by: | ||
7 | * | ||
8 | * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. | ||
9 | * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. | ||
10 | * | ||
11 | * | ||
12 | * Licensed under the GNU General Public License, version 2 (GPLv2). | ||
13 | */ | ||
14 | |||
15 | #undef extable_ent_size | ||
16 | #undef compare_extable | ||
17 | #undef do_func | ||
18 | #undef Elf_Addr | ||
19 | #undef Elf_Ehdr | ||
20 | #undef Elf_Shdr | ||
21 | #undef Elf_Rel | ||
22 | #undef Elf_Rela | ||
23 | #undef Elf_Sym | ||
24 | #undef ELF_R_SYM | ||
25 | #undef Elf_r_sym | ||
26 | #undef ELF_R_INFO | ||
27 | #undef Elf_r_info | ||
28 | #undef ELF_ST_BIND | ||
29 | #undef ELF_ST_TYPE | ||
30 | #undef fn_ELF_R_SYM | ||
31 | #undef fn_ELF_R_INFO | ||
32 | #undef uint_t | ||
33 | #undef _r | ||
34 | #undef _w | ||
35 | |||
36 | #ifdef SORTEXTABLE_64 | ||
37 | # define extable_ent_size 16 | ||
38 | # define compare_extable compare_extable_64 | ||
39 | # define do_func do64 | ||
40 | # define Elf_Addr Elf64_Addr | ||
41 | # define Elf_Ehdr Elf64_Ehdr | ||
42 | # define Elf_Shdr Elf64_Shdr | ||
43 | # define Elf_Rel Elf64_Rel | ||
44 | # define Elf_Rela Elf64_Rela | ||
45 | # define Elf_Sym Elf64_Sym | ||
46 | # define ELF_R_SYM ELF64_R_SYM | ||
47 | # define Elf_r_sym Elf64_r_sym | ||
48 | # define ELF_R_INFO ELF64_R_INFO | ||
49 | # define Elf_r_info Elf64_r_info | ||
50 | # define ELF_ST_BIND ELF64_ST_BIND | ||
51 | # define ELF_ST_TYPE ELF64_ST_TYPE | ||
52 | # define fn_ELF_R_SYM fn_ELF64_R_SYM | ||
53 | # define fn_ELF_R_INFO fn_ELF64_R_INFO | ||
54 | # define uint_t uint64_t | ||
55 | # define _r r8 | ||
56 | # define _w w8 | ||
57 | #else | ||
58 | # define extable_ent_size 8 | ||
59 | # define compare_extable compare_extable_32 | ||
60 | # define do_func do32 | ||
61 | # define Elf_Addr Elf32_Addr | ||
62 | # define Elf_Ehdr Elf32_Ehdr | ||
63 | # define Elf_Shdr Elf32_Shdr | ||
64 | # define Elf_Rel Elf32_Rel | ||
65 | # define Elf_Rela Elf32_Rela | ||
66 | # define Elf_Sym Elf32_Sym | ||
67 | # define ELF_R_SYM ELF32_R_SYM | ||
68 | # define Elf_r_sym Elf32_r_sym | ||
69 | # define ELF_R_INFO ELF32_R_INFO | ||
70 | # define Elf_r_info Elf32_r_info | ||
71 | # define ELF_ST_BIND ELF32_ST_BIND | ||
72 | # define ELF_ST_TYPE ELF32_ST_TYPE | ||
73 | # define fn_ELF_R_SYM fn_ELF32_R_SYM | ||
74 | # define fn_ELF_R_INFO fn_ELF32_R_INFO | ||
75 | # define uint_t uint32_t | ||
76 | # define _r r | ||
77 | # define _w w | ||
78 | #endif | ||
79 | |||
80 | static int compare_extable(const void *a, const void *b) | ||
81 | { | ||
82 | Elf_Addr av = _r(a); | ||
83 | Elf_Addr bv = _r(b); | ||
84 | |||
85 | if (av < bv) | ||
86 | return -1; | ||
87 | if (av > bv) | ||
88 | return 1; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static void | ||
93 | do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort) | ||
94 | { | ||
95 | Elf_Shdr *shdr; | ||
96 | Elf_Shdr *shstrtab_sec; | ||
97 | Elf_Shdr *strtab_sec = NULL; | ||
98 | Elf_Shdr *symtab_sec = NULL; | ||
99 | Elf_Shdr *extab_sec = NULL; | ||
100 | Elf_Sym *sym; | ||
101 | Elf_Sym *sort_needed_sym; | ||
102 | Elf_Shdr *sort_needed_sec; | ||
103 | Elf_Rel *relocs = NULL; | ||
104 | int relocs_size; | ||
105 | uint32_t *sort_done_location; | ||
106 | const char *secstrtab; | ||
107 | const char *strtab; | ||
108 | char *extab_image; | ||
109 | int extab_index = 0; | ||
110 | int i; | ||
111 | int idx; | ||
112 | |||
113 | shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff)); | ||
114 | shstrtab_sec = shdr + r2(&ehdr->e_shstrndx); | ||
115 | secstrtab = (const char *)ehdr + _r(&shstrtab_sec->sh_offset); | ||
116 | for (i = 0; i < r2(&ehdr->e_shnum); i++) { | ||
117 | idx = r(&shdr[i].sh_name); | ||
118 | if (strcmp(secstrtab + idx, "__ex_table") == 0) { | ||
119 | extab_sec = shdr + i; | ||
120 | extab_index = i; | ||
121 | } | ||
122 | if ((r(&shdr[i].sh_type) == SHT_REL || | ||
123 | r(&shdr[i].sh_type) == SHT_RELA) && | ||
124 | r(&shdr[i].sh_info) == extab_index) { | ||
125 | relocs = (void *)ehdr + _r(&shdr[i].sh_offset); | ||
126 | relocs_size = _r(&shdr[i].sh_size); | ||
127 | } | ||
128 | if (strcmp(secstrtab + idx, ".symtab") == 0) | ||
129 | symtab_sec = shdr + i; | ||
130 | if (strcmp(secstrtab + idx, ".strtab") == 0) | ||
131 | strtab_sec = shdr + i; | ||
132 | } | ||
133 | if (strtab_sec == NULL) { | ||
134 | fprintf(stderr, "no .strtab in file: %s\n", fname); | ||
135 | fail_file(); | ||
136 | } | ||
137 | if (symtab_sec == NULL) { | ||
138 | fprintf(stderr, "no .symtab in file: %s\n", fname); | ||
139 | fail_file(); | ||
140 | } | ||
141 | if (extab_sec == NULL) { | ||
142 | fprintf(stderr, "no __ex_table in file: %s\n", fname); | ||
143 | fail_file(); | ||
144 | } | ||
145 | strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset); | ||
146 | |||
147 | extab_image = (void *)ehdr + _r(&extab_sec->sh_offset); | ||
148 | |||
149 | if (custom_sort) { | ||
150 | custom_sort(extab_image, _r(&extab_sec->sh_size)); | ||
151 | } else { | ||
152 | int num_entries = _r(&extab_sec->sh_size) / extable_ent_size; | ||
153 | qsort(extab_image, num_entries, | ||
154 | extable_ent_size, compare_extable); | ||
155 | } | ||
156 | /* If there were relocations, we no longer need them. */ | ||
157 | if (relocs) | ||
158 | memset(relocs, 0, relocs_size); | ||
159 | |||
160 | /* find main_extable_sort_needed */ | ||
161 | sort_needed_sym = NULL; | ||
162 | for (i = 0; i < _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); i++) { | ||
163 | sym = (void *)ehdr + _r(&symtab_sec->sh_offset); | ||
164 | sym += i; | ||
165 | if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) | ||
166 | continue; | ||
167 | idx = r(&sym->st_name); | ||
168 | if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) { | ||
169 | sort_needed_sym = sym; | ||
170 | break; | ||
171 | } | ||
172 | } | ||
173 | if (sort_needed_sym == NULL) { | ||
174 | fprintf(stderr, | ||
175 | "no main_extable_sort_needed symbol in file: %s\n", | ||
176 | fname); | ||
177 | fail_file(); | ||
178 | } | ||
179 | sort_needed_sec = &shdr[r2(&sort_needed_sym->st_shndx)]; | ||
180 | sort_done_location = (void *)ehdr + | ||
181 | _r(&sort_needed_sec->sh_offset) + | ||
182 | _r(&sort_needed_sym->st_value) - | ||
183 | _r(&sort_needed_sec->sh_addr); | ||
184 | |||
185 | #if 1 | ||
186 | printf("sort done marker at %lx\n", | ||
187 | (unsigned long)((char *)sort_done_location - (char *)ehdr)); | ||
188 | #endif | ||
189 | /* We sorted it, clear the flag. */ | ||
190 | w(0, sort_done_location); | ||
191 | } | ||