2 # Check the stack usage of functions
4 # Copyright Joern Engel <joern@wh.fh-wedel.de>
5 # Inspired by Linus Torvalds
6 # Original idea maybe from Keith Owens
7 # s390 port and big speedup by Arnd Bergmann <arnd@bergmann-dalldorf.de>
8 # Modified to have simpler output format by Dan Kegel
11 # objdump -d vmlinux | stackcheck.pl [arch]
13 # find <moduledir> -name "*.o" | while read M; do
14 # objdump -d $M | perl ~/checkstack.pl <arch> | \
15 # sed "s/^/`basename $M`: /" ; done | \
16 # awk '/esp/ { print $5, $2, $4 }' | sort -nr
18 # TODO : Port to all architectures (one regex per arch)
22 # $re is used for three matches:
23 # $& (whole re) matches the complete objdump line with the stack growth
24 # $1 (first bracket) matches the code that will be displayed in the output
25 # $2 (second bracket) matches the size of the stack growth
27 # use anything else and feel the pain ;)
30 $x = "[0-9a-f]{1,5}"; # hex number
31 $d = "[0-9]{1,5}"; # decimal number
35 if ($arch =~ /^i[3456]86$/) {
36 #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp
37 $re = qr/^.*(sub \$(0x$x),\%esp)$/o;
38 $todec = sub { return hex($_[0]); };
39 } elsif ($arch =~ /^ia64$/) {
40 #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12
41 $re = qr/.*(adds.*r12=-($d),r12)/o;
42 $todec = sub { return $_[0]; };
43 } elsif ($arch =~ /^mips64$/) {
44 #8800402c: 67bdfff0 daddiu sp,sp,-16
45 $re = qr/.*(daddiu.*sp,sp,-($d))/o;
46 $todec = sub { return $_[0]; };
47 } elsif ($arch =~ /^mips$/) {
48 #88003254: 27bdffe0 addiu sp,sp,-32
49 $re = qr/.*(addiu.*sp,sp,-($d))/o;
50 $todec = sub { return $_[0]; };
51 } elsif ($arch =~ /^ppc$/) {
52 #c00029f4: 94 21 ff 30 stwu r1,-208(r1)
53 $re = qr/.*(stwu.*r1,-($x)\(r1\))/o;
54 $todec = sub { return hex($_[0]); };
55 } elsif ($arch =~ /^s390x?$/) {
56 # 11160: a7 fb ff 60 aghi %r15,-160
57 $re = qr/.*(ag?hi.*\%r15,-($d))/o;
58 $todec = sub { return $_[0]; };
60 print "Usage: objdump -d vmlinux | checkstack.pl [arch]\n";
61 print "where arch is i386, ia64, mips, mips64, ppc, or s390\n";
62 print "Each output line gives a function's stack usage, name\n";
63 print "Lines are output in order of decreasing stack usage\n";
64 die("wrong or unknown architecture\n");
68 $funcre = qr/^[0-9a-f]* \<(.*)\>:$/;
69 while ($line = <STDIN>) {
70 if ($line =~ m/$funcre/) {
71 ($func = $line) =~ s/$funcre/\1/;
74 if ($line =~ m/$re/) {
75 push(@stack, &$todec($2)." ".$func);
76 # don't expect more than one stack allocation per function
77 $func .= " ** bug **";
81 foreach (sort { $b - $a } (@stack)) {