Whamcloud - gitweb
5a8a96d6710da6694eb78ad932ee38b110eb4a94
[fs/lustre-release.git] / build / checkstack.pl
1 #!/usr/bin/perl
2 #       Check the stack usage of functions
3 #
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
9 #
10 #       Usage:
11 #       objdump -d vmlinux | stackcheck.pl [arch]
12 #
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
17
18 #       TODO :  Port to all architectures (one regex per arch)
19
20 # check for arch
21
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
26 #
27 # use anything else and feel the pain ;)
28 {
29         my $arch = shift;
30         $x      = "[0-9a-f]{3,5}";              # hex number     >= 256
31         $d      = "([0-9]{2}|[2-9])[0-9]{2}";   # decimal number >= 200
32         if ($arch eq "") {
33                 $arch = `uname -m`;
34         }
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 =~ 'x86_64') {
40                 #    2f60:      48 81 ec e8 05 00 00    sub    $0x5e8,%rsp
41                 $re = qr/^.*(add    \$(0x$x),\%rsp)$/o;
42                 $todec = sub { return hex($_[0]); };
43         } elsif ($arch =~ /^ia64$/) {
44                 #e0000000044011fc:       01 0f fc 8c     adds r12=-384,r12
45                 $re = qr/.*(adds.*r12=-($d),r12)/o;
46                 $todec = sub { return $_[0]; };
47         } elsif ($arch =~ /^mips64$/) {
48                 #8800402c:       67bdfff0        daddiu  sp,sp,-16
49                 $re = qr/.*(daddiu.*sp,sp,-($d))/o;
50                 $todec = sub { return $_[0]; };
51         } elsif ($arch =~ /^mips$/) {
52                 #88003254:       27bdffe0        addiu   sp,sp,-32
53                 $re = qr/.*(addiu.*sp,sp,-($d))/o;
54                 $todec = sub { return $_[0]; };
55         } elsif ($arch =~ /^ppc$/) {
56                 #c00029f4:       94 21 ff 30     stwu    r1,-208(r1)
57                 $re = qr/.*(stwu.*r1,-($x)\(r1\))/o;
58                 $todec = sub { return hex($_[0]); };
59         } elsif ($arch =~ /^s390x?$/) {
60                 #   11160:       a7 fb ff 60             aghi   %r15,-160
61                 $re = qr/.*(ag?hi.*\%r15,-($d))/o;
62                 $todec = sub { return $_[0]; };
63         } else {
64                 print "Usage:  objdump -d vmlinux | checkstack.pl [arch]\n";
65                 print "where arch is i386, ia64, mips, mips64, ppc, or s390\n";
66                 print "Each output line gives a function's stack usage, name\n";
67                 print "Lines are output in order of decreasing stack usage\n";
68                 die("wrong or unknown architecture\n");
69         }
70 }
71
72 $funcre = qr/^[0-9a-f]* \<(.*)\>:$/;
73 while ($line = <STDIN>) {
74         if ($line =~ m/$funcre/) {
75                 ($func = $line) =~ s/$funcre/\1/;
76                 chomp($func);
77         }
78         if ($line =~ m/$re/) {
79                 push(@stack, &$todec($2)." ".$func);
80                 # don't expect more than one stack allocation per function
81                 $func .= " ** bug **";
82         }
83 }
84
85 foreach (sort { $b - $a } (@stack)) {
86         print $_."\n";
87 }