diff options
Diffstat (limited to 'scripts/checkstack.pl')
-rwxr-xr-x | scripts/checkstack.pl | 107 |
1 files changed, 75 insertions, 32 deletions
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index b5980a2e3..7833554c8 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl @@ -1,10 +1,11 @@ -#!/usr/bin/perl +#!/usr/bin/env perl +# SPDX-License-Identifier: GPL-2.0 # Stolen from Linux kernel :) # Check the stack usage of functions # -# Copyright Joern Engel <joern@wh.fh-wedel.de> +# Copyright Joern Engel <joern@lazybastard.org> # Inspired by Linus Torvalds # Original idea maybe from Keith Owens # s390 port and big speedup by Arnd Bergmann <arnd@bergmann-dalldorf.de> @@ -14,41 +15,57 @@ # sh64 port by Paul Mundt # Random bits by Matt Mackall <mpm@selenic.com> # M68k port by Geert Uytterhoeven and Andreas Schwab +# blackfin port by Alex Landau +# AArch64, PARISC ports by Kyle McMartin +# sparc port by Martin Habets <errandir_news@mph.eclipse.co.uk> +# ppc64le port by Breno Leitao <leitao@debian.org> # # Usage: -# objdump -d vmlinux | checkstack.pl [arch] +# objdump -d vmlinux | scripts/checkstack.pl [arch] # # TODO : Port to all architectures (one regex per arch) +use strict; + # check for arch # # $re is used for two matches: # $& (whole re) matches the complete objdump line with the stack growth # $1 (first bracket) matches the size of the stack growth # +# $dre is similar, but for dynamic stack reductions: +# $& (whole re) matches the complete objdump line with the stack growth +# $1 (first bracket) matches the dynamic amount of the stack growth +# # use anything else and feel the pain ;) -my (@stack, $re, $x, $xs); +my (@stack, $re, $dre, $x, $xs, $funcre); { my $arch = shift; if ($arch eq "") { $arch = `uname -m`; - 1 while chomp $arch; + chomp($arch); } $x = "[0-9a-f]"; # hex character $xs = "[0-9a-f ]"; # hex character or space - if ($arch eq 'arm') { + $funcre = qr/^$x* <(.*)>:$/; + if ($arch eq 'aarch64') { + #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp, #-80]! + #a110: d11643ff sub sp, sp, #0x590 + $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o; + $dre = qr/^.*sub.*sp, sp, #(0x$x{1,8})/o; + } elsif ($arch eq 'arm') { #c0008ffc: e24dd064 sub sp, sp, #100 ; 0x64 $re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o; + } elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) { + #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp + # or + # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp + $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%(e|r)sp$/o; + $dre = qr/^.*[as][du][db] (%.*),\%(e|r)sp$/o; } elsif ($arch eq 'blackfin') { # 52: 00 e8 03 00 LINK 0xc; $re = qr/.*LINK (0x$x{1,5});$/o; - } elsif ($arch =~ /^i[3456]86$/) { - #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp - $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o; - } elsif ($arch eq 'x86_64') { - # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp - $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o; } elsif ($arch eq 'ia64') { #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; @@ -62,42 +79,43 @@ my (@stack, $re, $x, $xs); } elsif ($arch eq 'mips') { #88003254: 27bdffe0 addiu sp,sp,-32 $re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; - } elsif ($arch eq 'ppc') { - #c00029f4: 94 21 ff 30 stwu r1,-208(r1) - $re = qr/.*stwu.*r1,-($x{1,8})\(r1\)/o; - } elsif ($arch eq 'ppc64') { - #XXX - $re = qr/.*stdu.*r1,-($x{1,8})\(r1\)/o; - } elsif ($arch eq 'powerpc') { + } elsif ($arch eq 'nios2') { + #25a8: defffb04 addi sp,sp,-20 + $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; + } elsif ($arch eq 'openrisc') { + # c000043c: 9c 21 fe f0 l.addi r1,r1,-272 + $re = qr/.*l\.addi.*r1,r1,-(([0-9]{2}|[3-9])[0-9]{2})/o; + } elsif ($arch eq 'parisc' || $arch eq 'parisc64') { + $re = qr/.*ldo ($x{1,8})\(sp\),sp/o; + } elsif ($arch eq 'powerpc' || $arch =~ /^ppc(64)?(le)?$/ ) { + # powerpc : 94 21 ff 30 stwu r1,-208(r1) + # ppc64(le) : 81 ff 21 f8 stdu r1,-128(r1) $re = qr/.*st[dw]u.*r1,-($x{1,8})\(r1\)/o; } elsif ($arch =~ /^s390x?$/) { # 11160: a7 fb ff 60 aghi %r15,-160 - $re = qr/.*ag?hi.*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})/o; + # or + # 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15) + $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2}) + (?:\(\%r15\))?$/ox; } elsif ($arch =~ /^sh64$/) { #XXX: we only check for the immediate case presently, # though we will want to check for the movi/sub # pair for larger users. -- PFM. #a00048e0: d4fc40f0 addi.l r15,-240,r15 $re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o; + } elsif ($arch eq 'sparc' || $arch eq 'sparc64') { + # f0019d10: 9d e3 bf 90 save %sp, -112, %sp + $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o; } else { - print("wrong or unknown architecture\n"); + print("wrong or unknown architecture \"$arch\"\n"); exit } } -sub bysize($) { - my ($asize, $bsize); - ($asize = $a) =~ s/.*: *(.*)$/$1/; - ($bsize = $b) =~ s/.*: *(.*)$/$1/; - $bsize <=> $asize -} - # # main() # -my $funcre = qr/^$x* <(.*)>:$/; -my $func; -my $file, $lastslash; +my ($func, $file, $lastslash); while (my $line = <STDIN>) { if ($line =~ m/$funcre/) { @@ -137,6 +155,31 @@ while (my $line = <STDIN>) { next if ($size < 100); push @stack, "$intro$size\n"; } + elsif (defined $dre && $line =~ m/$dre/) { + my $size = "Dynamic ($1)"; + + next if $line !~ m/^($xs*)/; + my $addr = $1; + $addr =~ s/ /0/g; + $addr = "0x$addr"; + + #bbox: was: my $intro = "$addr $func [$file]:"; + my $intro = "$func [$file]:"; + my $padlen = 56 - length($intro); + while ($padlen > 0) { + $intro .= ' '; + $padlen -= 8; + } + push @stack, "$intro$size\n"; + } +} + +sub bysize($) { + my ($asize, $bsize); + ($asize = $a) =~ s/.*: *(.*)$/$1/; + ($bsize = $b) =~ s/.*: *(.*)$/$1/; + $bsize <=> $asize } -print sort bysize @stack; +# Sort output by size (last field) +print sort { ($b =~ /:\t*(\d+)$/)[0] <=> ($a =~ /:\t*(\d+)$/)[0] } @stack; |