diff options
author | Ron Yorston <rmy@pobox.com> | 2019-02-12 08:43:06 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2019-02-12 08:43:06 +0000 |
commit | 7a8bd5ae33d8c390763f0787afe6b8c495e2d978 (patch) | |
tree | 29b0abb320d73b37f4fa4d9b355b3b32db42e836 /scripts | |
parent | 0eda390d68c456975289471e68b615ae096ab33b (diff) | |
parent | f81e0120f4478c58e126bcadb19b9954ed184e8f (diff) | |
download | busybox-w32-7a8bd5ae33d8c390763f0787afe6b8c495e2d978.tar.gz busybox-w32-7a8bd5ae33d8c390763f0787afe6b8c495e2d978.tar.bz2 busybox-w32-7a8bd5ae33d8c390763f0787afe6b8c495e2d978.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/checkstack.pl | 108 |
1 files changed, 76 insertions, 32 deletions
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index 55cdd78c1..cf912e0fb 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl | |||
@@ -1,10 +1,11 @@ | |||
1 | #!/usr/bin/perl | 1 | #!/usr/bin/env perl |
2 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | 3 | ||
3 | # Stolen from Linux kernel :) | 4 | # Stolen from Linux kernel :) |
4 | 5 | ||
5 | # Check the stack usage of functions | 6 | # Check the stack usage of functions |
6 | # | 7 | # |
7 | # Copyright Joern Engel <joern@wh.fh-wedel.de> | 8 | # Copyright Joern Engel <joern@lazybastard.org> |
8 | # Inspired by Linus Torvalds | 9 | # Inspired by Linus Torvalds |
9 | # Original idea maybe from Keith Owens | 10 | # Original idea maybe from Keith Owens |
10 | # s390 port and big speedup by Arnd Bergmann <arnd@bergmann-dalldorf.de> | 11 | # s390 port and big speedup by Arnd Bergmann <arnd@bergmann-dalldorf.de> |
@@ -14,40 +15,57 @@ | |||
14 | # sh64 port by Paul Mundt | 15 | # sh64 port by Paul Mundt |
15 | # Random bits by Matt Mackall <mpm@selenic.com> | 16 | # Random bits by Matt Mackall <mpm@selenic.com> |
16 | # M68k port by Geert Uytterhoeven and Andreas Schwab | 17 | # M68k port by Geert Uytterhoeven and Andreas Schwab |
18 | # blackfin port by Alex Landau | ||
19 | # AArch64, PARISC ports by Kyle McMartin | ||
20 | # sparc port by Martin Habets <errandir_news@mph.eclipse.co.uk> | ||
21 | # ppc64le port by Breno Leitao <leitao@debian.org> | ||
17 | # | 22 | # |
18 | # Usage: | 23 | # Usage: |
19 | # objdump -d vmlinux | checkstack.pl [arch] | 24 | # objdump -d vmlinux | scripts/checkstack.pl [arch] |
20 | # | 25 | # |
21 | # TODO : Port to all architectures (one regex per arch) | 26 | # TODO : Port to all architectures (one regex per arch) |
22 | 27 | ||
28 | use strict; | ||
29 | |||
23 | # check for arch | 30 | # check for arch |
24 | # | 31 | # |
25 | # $re is used for two matches: | 32 | # $re is used for two matches: |
26 | # $& (whole re) matches the complete objdump line with the stack growth | 33 | # $& (whole re) matches the complete objdump line with the stack growth |
27 | # $1 (first bracket) matches the size of the stack growth | 34 | # $1 (first bracket) matches the size of the stack growth |
28 | # | 35 | # |
36 | # $dre is similar, but for dynamic stack reductions: | ||
37 | # $& (whole re) matches the complete objdump line with the stack growth | ||
38 | # $1 (first bracket) matches the dynamic amount of the stack growth | ||
39 | # | ||
29 | # use anything else and feel the pain ;) | 40 | # use anything else and feel the pain ;) |
30 | my (@stack, $re, $x, $xs); | 41 | my (@stack, $re, $dre, $x, $xs, $funcre); |
31 | { | 42 | { |
32 | my $arch = shift; | 43 | my $arch = shift; |
33 | if ($arch eq "") { | 44 | if ($arch eq "") { |
34 | $arch = `uname -m`; | 45 | $arch = `uname -m`; |
46 | chomp($arch); | ||
35 | } | 47 | } |
36 | 48 | ||
37 | $x = "[0-9a-f]"; # hex character | 49 | $x = "[0-9a-f]"; # hex character |
38 | $xs = "[0-9a-f ]"; # hex character or space | 50 | $xs = "[0-9a-f ]"; # hex character or space |
39 | if ($arch eq 'arm') { | 51 | $funcre = qr/^$x* <(.*)>:$/; |
52 | if ($arch eq 'aarch64') { | ||
53 | #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp, #-80]! | ||
54 | #a110: d11643ff sub sp, sp, #0x590 | ||
55 | $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o; | ||
56 | $dre = qr/^.*sub.*sp, sp, #(0x$x{1,8})/o; | ||
57 | } elsif ($arch eq 'arm') { | ||
40 | #c0008ffc: e24dd064 sub sp, sp, #100 ; 0x64 | 58 | #c0008ffc: e24dd064 sub sp, sp, #100 ; 0x64 |
41 | $re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o; | 59 | $re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o; |
60 | } elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) { | ||
61 | #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp | ||
62 | # or | ||
63 | # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp | ||
64 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%(e|r)sp$/o; | ||
65 | $dre = qr/^.*[as][du][db] (%.*),\%(e|r)sp$/o; | ||
42 | } elsif ($arch eq 'blackfin') { | 66 | } elsif ($arch eq 'blackfin') { |
43 | # 52: 00 e8 03 00 LINK 0xc; | 67 | # 52: 00 e8 03 00 LINK 0xc; |
44 | $re = qr/.*LINK (0x$x{1,5});$/o; | 68 | $re = qr/.*[[:space:]]LINK[[:space:]]*(0x$x{1,8})/o; |
45 | } elsif ($arch =~ /^i[3456]86$/) { | ||
46 | #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp | ||
47 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o; | ||
48 | } elsif ($arch eq 'x86_64') { | ||
49 | # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp | ||
50 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o; | ||
51 | } elsif ($arch eq 'ia64') { | 69 | } elsif ($arch eq 'ia64') { |
52 | #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 | 70 | #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 |
53 | $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; | 71 | $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; |
@@ -61,42 +79,43 @@ my (@stack, $re, $x, $xs); | |||
61 | } elsif ($arch eq 'mips') { | 79 | } elsif ($arch eq 'mips') { |
62 | #88003254: 27bdffe0 addiu sp,sp,-32 | 80 | #88003254: 27bdffe0 addiu sp,sp,-32 |
63 | $re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; | 81 | $re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; |
64 | } elsif ($arch eq 'ppc') { | 82 | } elsif ($arch eq 'nios2') { |
65 | #c00029f4: 94 21 ff 30 stwu r1,-208(r1) | 83 | #25a8: defffb04 addi sp,sp,-20 |
66 | $re = qr/.*stwu.*r1,-($x{1,8})\(r1\)/o; | 84 | $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; |
67 | } elsif ($arch eq 'ppc64') { | 85 | } elsif ($arch eq 'openrisc') { |
68 | #XXX | 86 | # c000043c: 9c 21 fe f0 l.addi r1,r1,-272 |
69 | $re = qr/.*stdu.*r1,-($x{1,8})\(r1\)/o; | 87 | $re = qr/.*l\.addi.*r1,r1,-(([0-9]{2}|[3-9])[0-9]{2})/o; |
70 | } elsif ($arch eq 'powerpc') { | 88 | } elsif ($arch eq 'parisc' || $arch eq 'parisc64') { |
89 | $re = qr/.*ldo ($x{1,8})\(sp\),sp/o; | ||
90 | } elsif ($arch eq 'powerpc' || $arch =~ /^ppc(64)?(le)?$/ ) { | ||
91 | # powerpc : 94 21 ff 30 stwu r1,-208(r1) | ||
92 | # ppc64(le) : 81 ff 21 f8 stdu r1,-128(r1) | ||
71 | $re = qr/.*st[dw]u.*r1,-($x{1,8})\(r1\)/o; | 93 | $re = qr/.*st[dw]u.*r1,-($x{1,8})\(r1\)/o; |
72 | } elsif ($arch =~ /^s390x?$/) { | 94 | } elsif ($arch =~ /^s390x?$/) { |
73 | # 11160: a7 fb ff 60 aghi %r15,-160 | 95 | # 11160: a7 fb ff 60 aghi %r15,-160 |
74 | $re = qr/.*ag?hi.*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})/o; | 96 | # or |
97 | # 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15) | ||
98 | $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2}) | ||
99 | (?:\(\%r15\))?$/ox; | ||
75 | } elsif ($arch =~ /^sh64$/) { | 100 | } elsif ($arch =~ /^sh64$/) { |
76 | #XXX: we only check for the immediate case presently, | 101 | #XXX: we only check for the immediate case presently, |
77 | # though we will want to check for the movi/sub | 102 | # though we will want to check for the movi/sub |
78 | # pair for larger users. -- PFM. | 103 | # pair for larger users. -- PFM. |
79 | #a00048e0: d4fc40f0 addi.l r15,-240,r15 | 104 | #a00048e0: d4fc40f0 addi.l r15,-240,r15 |
80 | $re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o; | 105 | $re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o; |
106 | } elsif ($arch eq 'sparc' || $arch eq 'sparc64') { | ||
107 | # f0019d10: 9d e3 bf 90 save %sp, -112, %sp | ||
108 | $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o; | ||
81 | } else { | 109 | } else { |
82 | print("wrong or unknown architecture\n"); | 110 | print("wrong or unknown architecture \"$arch\"\n"); |
83 | exit | 111 | exit |
84 | } | 112 | } |
85 | } | 113 | } |
86 | 114 | ||
87 | sub bysize($) { | ||
88 | my ($asize, $bsize); | ||
89 | ($asize = $a) =~ s/.*: *(.*)$/$1/; | ||
90 | ($bsize = $b) =~ s/.*: *(.*)$/$1/; | ||
91 | $bsize <=> $asize | ||
92 | } | ||
93 | |||
94 | # | 115 | # |
95 | # main() | 116 | # main() |
96 | # | 117 | # |
97 | my $funcre = qr/^$x* <(.*)>:$/; | 118 | my ($func, $file, $lastslash); |
98 | my $func; | ||
99 | my $file, $lastslash; | ||
100 | 119 | ||
101 | while (my $line = <STDIN>) { | 120 | while (my $line = <STDIN>) { |
102 | if ($line =~ m/$funcre/) { | 121 | if ($line =~ m/$funcre/) { |
@@ -136,6 +155,31 @@ while (my $line = <STDIN>) { | |||
136 | next if ($size < 100); | 155 | next if ($size < 100); |
137 | push @stack, "$intro$size\n"; | 156 | push @stack, "$intro$size\n"; |
138 | } | 157 | } |
158 | elsif (defined $dre && $line =~ m/$dre/) { | ||
159 | my $size = "Dynamic ($1)"; | ||
160 | |||
161 | next if $line !~ m/^($xs*)/; | ||
162 | my $addr = $1; | ||
163 | $addr =~ s/ /0/g; | ||
164 | $addr = "0x$addr"; | ||
165 | |||
166 | #bbox: was: my $intro = "$addr $func [$file]:"; | ||
167 | my $intro = "$func [$file]:"; | ||
168 | my $padlen = 56 - length($intro); | ||
169 | while ($padlen > 0) { | ||
170 | $intro .= ' '; | ||
171 | $padlen -= 8; | ||
172 | } | ||
173 | push @stack, "$intro$size\n"; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | sub bysize($) { | ||
178 | my ($asize, $bsize); | ||
179 | ($asize = $a) =~ s/.*: *(.*)$/$1/; | ||
180 | ($bsize = $b) =~ s/.*: *(.*)$/$1/; | ||
181 | $bsize <=> $asize | ||
139 | } | 182 | } |
140 | 183 | ||
141 | print sort bysize @stack; | 184 | # Sort output by size (last field) |
185 | print sort { ($b =~ /:\t*(\d+)$/)[0] <=> ($a =~ /:\t*(\d+)$/)[0] } @stack; | ||