![]() |
|
|||
0001 #!/usr/bin/env perl 0002 # SPDX-License-Identifier: GPL-2.0 0003 0004 # Check the stack usage of functions 0005 # 0006 # Copyright Joern Engel <joern@lazybastard.org> 0007 # Inspired by Linus Torvalds 0008 # Original idea maybe from Keith Owens 0009 # s390 port and big speedup by Arnd Bergmann <arnd@bergmann-dalldorf.de> 0010 # Mips port by Juan Quintela <quintela@mandrakesoft.com> 0011 # IA64 port via Andreas Dilger 0012 # Arm port by Holger Schurig 0013 # sh64 port by Paul Mundt 0014 # Random bits by Matt Mackall <mpm@selenic.com> 0015 # M68k port by Geert Uytterhoeven and Andreas Schwab 0016 # AArch64, PARISC ports by Kyle McMartin 0017 # sparc port by Martin Habets <errandir_news@mph.eclipse.co.uk> 0018 # ppc64le port by Breno Leitao <leitao@debian.org> 0019 # riscv port by Wadim Mueller <wafgo01@gmail.com> 0020 # 0021 # Usage: 0022 # objdump -d vmlinux | scripts/checkstack.pl [arch] 0023 # 0024 # TODO : Port to all architectures (one regex per arch) 0025 0026 use strict; 0027 0028 # check for arch 0029 # 0030 # $re is used for two matches: 0031 # $& (whole re) matches the complete objdump line with the stack growth 0032 # $1 (first bracket) matches the size of the stack growth 0033 # 0034 # $dre is similar, but for dynamic stack redutions: 0035 # $& (whole re) matches the complete objdump line with the stack growth 0036 # $1 (first bracket) matches the dynamic amount of the stack growth 0037 # 0038 # $sub: subroutine for special handling to check stack usage. 0039 # 0040 # use anything else and feel the pain ;) 0041 my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack); 0042 { 0043 my $arch = shift; 0044 if ($arch eq "") { 0045 $arch = `uname -m`; 0046 chomp($arch); 0047 } 0048 0049 $min_stack = shift; 0050 if ($min_stack eq "" || $min_stack !~ /^\d+$/) { 0051 $min_stack = 100; 0052 } 0053 0054 $x = "[0-9a-f]"; # hex character 0055 $xs = "[0-9a-f ]"; # hex character or space 0056 $funcre = qr/^$x* <(.*)>:$/; 0057 if ($arch =~ '^(aarch|arm)64$') { 0058 #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp, #-80]! 0059 #a110: d11643ff sub sp, sp, #0x590 0060 $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o; 0061 $dre = qr/^.*sub.*sp, sp, #(0x$x{1,8})/o; 0062 } elsif ($arch eq 'arm') { 0063 #c0008ffc: e24dd064 sub sp, sp, #100 ; 0x64 0064 $re = qr/.*sub.*sp, sp, #([0-9]{1,4})/o; 0065 $sub = \&arm_push_handling; 0066 } elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) { 0067 #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp 0068 # or 0069 # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp 0070 $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%(e|r)sp$/o; 0071 $dre = qr/^.*[as][du][db] (%.*),\%(e|r)sp$/o; 0072 } elsif ($arch eq 'ia64') { 0073 #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 0074 $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; 0075 } elsif ($arch eq 'm68k') { 0076 # 2b6c: 4e56 fb70 linkw %fp,#-1168 0077 # 1df770: defc ffe4 addaw #-28,%sp 0078 $re = qr/.*(?:linkw %fp,|addaw )#-([0-9]{1,4})(?:,%sp)?$/o; 0079 } elsif ($arch eq 'mips64') { 0080 #8800402c: 67bdfff0 daddiu sp,sp,-16 0081 $re = qr/.*daddiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; 0082 } elsif ($arch eq 'mips') { 0083 #88003254: 27bdffe0 addiu sp,sp,-32 0084 $re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; 0085 } elsif ($arch eq 'nios2') { 0086 #25a8: defffb04 addi sp,sp,-20 0087 $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; 0088 } elsif ($arch eq 'openrisc') { 0089 # c000043c: 9c 21 fe f0 l.addi r1,r1,-272 0090 $re = qr/.*l\.addi.*r1,r1,-(([0-9]{2}|[3-9])[0-9]{2})/o; 0091 } elsif ($arch eq 'parisc' || $arch eq 'parisc64') { 0092 $re = qr/.*ldo ($x{1,8})\(sp\),sp/o; 0093 } elsif ($arch eq 'powerpc' || $arch =~ /^ppc(64)?(le)?$/ ) { 0094 # powerpc : 94 21 ff 30 stwu r1,-208(r1) 0095 # ppc64(le) : 81 ff 21 f8 stdu r1,-128(r1) 0096 $re = qr/.*st[dw]u.*r1,-($x{1,8})\(r1\)/o; 0097 } elsif ($arch =~ /^s390x?$/) { 0098 # 11160: a7 fb ff 60 aghi %r15,-160 0099 # or 0100 # 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15) 0101 $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2}) 0102 (?:\(\%r15\))?$/ox; 0103 } elsif ($arch =~ /^sh64$/) { 0104 #XXX: we only check for the immediate case presently, 0105 # though we will want to check for the movi/sub 0106 # pair for larger users. -- PFM. 0107 #a00048e0: d4fc40f0 addi.l r15,-240,r15 0108 $re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o; 0109 } elsif ($arch eq 'sparc' || $arch eq 'sparc64') { 0110 # f0019d10: 9d e3 bf 90 save %sp, -112, %sp 0111 $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o; 0112 } elsif ($arch =~ /^riscv(64)?$/) { 0113 #ffffffff8036e868: c2010113 addi sp,sp,-992 0114 $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; 0115 } else { 0116 print("wrong or unknown architecture \"$arch\"\n"); 0117 exit 0118 } 0119 } 0120 0121 # 0122 # To count stack usage of push {*, fp, ip, lr, pc} instruction in ARM, 0123 # if FRAME POINTER is enabled. 0124 # e.g. c01f0d48: e92ddff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} 0125 # 0126 sub arm_push_handling { 0127 my $regex = qr/.*push.*fp, ip, lr, pc}/o; 0128 my $size = 0; 0129 my $line_arg = shift; 0130 0131 if ($line_arg =~ m/$regex/) { 0132 $size = $line_arg =~ tr/,//; 0133 $size = ($size + 1) * 4; 0134 } 0135 0136 return $size; 0137 } 0138 0139 # 0140 # main() 0141 # 0142 my ($func, $file, $lastslash, $total_size, $addr, $intro); 0143 0144 $total_size = 0; 0145 0146 while (my $line = <STDIN>) { 0147 if ($line =~ m/$funcre/) { 0148 $func = $1; 0149 next if $line !~ m/^($xs*)/; 0150 if ($total_size > $min_stack) { 0151 push @stack, "$intro$total_size\n"; 0152 } 0153 0154 $addr = $1; 0155 $addr =~ s/ /0/g; 0156 $addr = "0x$addr"; 0157 0158 $intro = "$addr $func [$file]:"; 0159 my $padlen = 56 - length($intro); 0160 while ($padlen > 0) { 0161 $intro .= ' '; 0162 $padlen -= 8; 0163 } 0164 0165 $total_size = 0; 0166 } 0167 elsif ($line =~ m/(.*):\s*file format/) { 0168 $file = $1; 0169 $file =~ s/\.ko//; 0170 $lastslash = rindex($file, "/"); 0171 if ($lastslash != -1) { 0172 $file = substr($file, $lastslash + 1); 0173 } 0174 } 0175 elsif ($line =~ m/$re/) { 0176 my $size = $1; 0177 $size = hex($size) if ($size =~ /^0x/); 0178 0179 if ($size > 0xf0000000) { 0180 $size = - $size; 0181 $size += 0x80000000; 0182 $size += 0x80000000; 0183 } 0184 next if ($size > 0x10000000); 0185 0186 $total_size += $size; 0187 } 0188 elsif (defined $dre && $line =~ m/$dre/) { 0189 my $size = $1; 0190 0191 $size = hex($size) if ($size =~ /^0x/); 0192 $total_size += $size; 0193 } 0194 elsif (defined $sub) { 0195 my $size = &$sub($line); 0196 0197 $total_size += $size; 0198 } 0199 } 0200 if ($total_size > $min_stack) { 0201 push @stack, "$intro$total_size\n"; 0202 } 0203 0204 # Sort output by size (last field) 0205 print sort { ($b =~ /:\t*(\d+)$/)[0] <=> ($a =~ /:\t*(\d+)$/)[0] } @stack;
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |