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]{2,5}"; # hex number >= 256
31 $d = "([0-9]{2}|[2-9])[0-9]{2}"; # decimal number >= 200
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]; };
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");
72 $funcre = qr/^[0-9a-f]* \<(.*)\>:$/;
73 while ($line = <STDIN>) {
74 if ($line =~ m/$funcre/) {
75 ($func = $line) =~ s/$funcre/\1/;
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 **";
85 foreach (sort { $b - $a } (@stack)) {