| .. | .. |
|---|
| 34 | 34 | # $& (whole re) matches the complete objdump line with the stack growth |
|---|
| 35 | 35 | # $1 (first bracket) matches the dynamic amount of the stack growth |
|---|
| 36 | 36 | # |
|---|
| 37 | +# $sub: subroutine for special handling to check stack usage. |
|---|
| 38 | +# |
|---|
| 37 | 39 | # use anything else and feel the pain ;) |
|---|
| 38 | | -my (@stack, $re, $dre, $x, $xs, $funcre); |
|---|
| 40 | +my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack); |
|---|
| 39 | 41 | { |
|---|
| 40 | 42 | my $arch = shift; |
|---|
| 41 | 43 | if ($arch eq "") { |
|---|
| .. | .. |
|---|
| 43 | 45 | chomp($arch); |
|---|
| 44 | 46 | } |
|---|
| 45 | 47 | |
|---|
| 48 | + $min_stack = shift; |
|---|
| 49 | + if ($min_stack eq "" || $min_stack !~ /^\d+$/) { |
|---|
| 50 | + $min_stack = 100; |
|---|
| 51 | + } |
|---|
| 52 | + |
|---|
| 46 | 53 | $x = "[0-9a-f]"; # hex character |
|---|
| 47 | 54 | $xs = "[0-9a-f ]"; # hex character or space |
|---|
| 48 | 55 | $funcre = qr/^$x* <(.*)>:$/; |
|---|
| 49 | 56 | if ($arch =~ '^(aarch|arm)64$') { |
|---|
| 50 | 57 | #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp, #-80]! |
|---|
| 58 | + #a110: d11643ff sub sp, sp, #0x590 |
|---|
| 51 | 59 | $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o; |
|---|
| 60 | + $dre = qr/^.*sub.*sp, sp, #(0x$x{1,8})/o; |
|---|
| 52 | 61 | } elsif ($arch eq 'arm') { |
|---|
| 53 | 62 | #c0008ffc: e24dd064 sub sp, sp, #100 ; 0x64 |
|---|
| 54 | | - $re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o; |
|---|
| 63 | + $re = qr/.*sub.*sp, sp, #([0-9]{1,4})/o; |
|---|
| 64 | + $sub = \&arm_push_handling; |
|---|
| 55 | 65 | } elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) { |
|---|
| 56 | 66 | #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp |
|---|
| 57 | 67 | # or |
|---|
| .. | .. |
|---|
| 105 | 115 | } |
|---|
| 106 | 116 | |
|---|
| 107 | 117 | # |
|---|
| 118 | +# To count stack usage of push {*, fp, ip, lr, pc} instruction in ARM, |
|---|
| 119 | +# if FRAME POINTER is enabled. |
|---|
| 120 | +# e.g. c01f0d48: e92ddff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} |
|---|
| 121 | +# |
|---|
| 122 | +sub arm_push_handling { |
|---|
| 123 | + my $regex = qr/.*push.*fp, ip, lr, pc}/o; |
|---|
| 124 | + my $size = 0; |
|---|
| 125 | + my $line_arg = shift; |
|---|
| 126 | + |
|---|
| 127 | + if ($line_arg =~ m/$regex/) { |
|---|
| 128 | + $size = $line_arg =~ tr/,//; |
|---|
| 129 | + $size = ($size + 1) * 4; |
|---|
| 130 | + } |
|---|
| 131 | + |
|---|
| 132 | + return $size; |
|---|
| 133 | +} |
|---|
| 134 | + |
|---|
| 135 | +# |
|---|
| 108 | 136 | # main() |
|---|
| 109 | 137 | # |
|---|
| 110 | | -my ($func, $file, $lastslash); |
|---|
| 138 | +my ($func, $file, $lastslash, $total_size, $addr, $intro); |
|---|
| 139 | + |
|---|
| 140 | +$total_size = 0; |
|---|
| 111 | 141 | |
|---|
| 112 | 142 | while (my $line = <STDIN>) { |
|---|
| 113 | 143 | if ($line =~ m/$funcre/) { |
|---|
| 114 | 144 | $func = $1; |
|---|
| 145 | + next if $line !~ m/^($xs*)/; |
|---|
| 146 | + if ($total_size > $min_stack) { |
|---|
| 147 | + push @stack, "$intro$total_size\n"; |
|---|
| 148 | + } |
|---|
| 149 | + |
|---|
| 150 | + $addr = $1; |
|---|
| 151 | + $addr =~ s/ /0/g; |
|---|
| 152 | + $addr = "0x$addr"; |
|---|
| 153 | + |
|---|
| 154 | + $intro = "$addr $func [$file]:"; |
|---|
| 155 | + my $padlen = 56 - length($intro); |
|---|
| 156 | + while ($padlen > 0) { |
|---|
| 157 | + $intro .= ' '; |
|---|
| 158 | + $padlen -= 8; |
|---|
| 159 | + } |
|---|
| 160 | + |
|---|
| 161 | + $total_size = 0; |
|---|
| 115 | 162 | } |
|---|
| 116 | 163 | elsif ($line =~ m/(.*):\s*file format/) { |
|---|
| 117 | 164 | $file = $1; |
|---|
| .. | .. |
|---|
| 132 | 179 | } |
|---|
| 133 | 180 | next if ($size > 0x10000000); |
|---|
| 134 | 181 | |
|---|
| 135 | | - next if $line !~ m/^($xs*)/; |
|---|
| 136 | | - my $addr = $1; |
|---|
| 137 | | - $addr =~ s/ /0/g; |
|---|
| 138 | | - $addr = "0x$addr"; |
|---|
| 139 | | - |
|---|
| 140 | | - my $intro = "$addr $func [$file]:"; |
|---|
| 141 | | - my $padlen = 56 - length($intro); |
|---|
| 142 | | - while ($padlen > 0) { |
|---|
| 143 | | - $intro .= ' '; |
|---|
| 144 | | - $padlen -= 8; |
|---|
| 145 | | - } |
|---|
| 146 | | - next if ($size < 100); |
|---|
| 147 | | - push @stack, "$intro$size\n"; |
|---|
| 182 | + $total_size += $size; |
|---|
| 148 | 183 | } |
|---|
| 149 | 184 | elsif (defined $dre && $line =~ m/$dre/) { |
|---|
| 150 | | - my $size = "Dynamic ($1)"; |
|---|
| 185 | + my $size = $1; |
|---|
| 151 | 186 | |
|---|
| 152 | | - next if $line !~ m/^($xs*)/; |
|---|
| 153 | | - my $addr = $1; |
|---|
| 154 | | - $addr =~ s/ /0/g; |
|---|
| 155 | | - $addr = "0x$addr"; |
|---|
| 156 | | - |
|---|
| 157 | | - my $intro = "$addr $func [$file]:"; |
|---|
| 158 | | - my $padlen = 56 - length($intro); |
|---|
| 159 | | - while ($padlen > 0) { |
|---|
| 160 | | - $intro .= ' '; |
|---|
| 161 | | - $padlen -= 8; |
|---|
| 162 | | - } |
|---|
| 163 | | - push @stack, "$intro$size\n"; |
|---|
| 187 | + $size = hex($size) if ($size =~ /^0x/); |
|---|
| 188 | + $total_size += $size; |
|---|
| 164 | 189 | } |
|---|
| 190 | + elsif (defined $sub) { |
|---|
| 191 | + my $size = &$sub($line); |
|---|
| 192 | + |
|---|
| 193 | + $total_size += $size; |
|---|
| 194 | + } |
|---|
| 195 | +} |
|---|
| 196 | +if ($total_size > $min_stack) { |
|---|
| 197 | + push @stack, "$intro$total_size\n"; |
|---|
| 165 | 198 | } |
|---|
| 166 | 199 | |
|---|
| 167 | 200 | # Sort output by size (last field) |
|---|