* Functions with Large Stack Usage
@ 2002-08-27 18:08 Danny Cox
2002-08-28 3:56 ` Keith Owens
0 siblings, 1 reply; 2+ messages in thread
From: Danny Cox @ 2002-08-27 18:08 UTC (permalink / raw)
To: Linux Kernel List
[-- Attachment #1: Type: text/plain, Size: 2091 bytes --]
Hi,
After having read of the stack overflow "issues" awhile back, a couple
of ideas gelled, with this script as a result. The script finds
functions that use a large (changeable) amount of stack space. Note:
it's heuristic, it's static, it only looks at compiled-in functions, and
says nothing about the dynamic system. It DOES point out functions that
may (MAY) need to be examined closer.
The functions and their sizes are:
check huft_build (stack 1436)
check inflate_fixed (stack 1168)
check inflate_dynamic (stack 1308)
check pci_sanity_check (stack 804)
check pcibios_fixup_peer_bridges (stack 804)
check elf_core_dump (stack 592)
check xfs_ioctl (stack 752)
check semctl_main (stack 588)
check extract_entropy (stack 708)
check vt_ioctl (stack 756)
check ide_unregister (stack 880)
check cdrom_buffer_sectors (stack 516)
check cdrom_read_intr (stack 532)
check cdrom_slot_status (stack 1040)
check cdrom_number_of_slots (stack 1040)
check cdrom_select_disc (stack 1040)
check cdrom_ioctl (stack 1084)
check pci_do_scan_bus (stack 680)
This is from kernel 2.4.19-xfs (yes, I'm an XFS weenie ;-).
How it works: With Keith Owens' KDB patch, one may compile the kernel
with frame pointers. With the Disassemble::X86 Perl module from CPAN
(http://search.cpan.org/author/BOBMATH/Disassemble-X86-0.12/X86.pm),
it's easy. It requires the vmlinux and System.map files, and for each
function looks at the first 10 instructions for the 'sub esp,N'. The N
is the number of bytes of stack used.
I'm not subscribed to this list. I tried once, but it's much too busy
for me to keep up with, and actually get any work done ;-). So, please
CC: me if you wish me to be included.
I apologize in advance for 1) the C-like Perl code, and 2) for
attaching it. I've tried an in-line paste before, but it wraps, and
makes it even uglier than before.
Comments, bugs, and enhancements are encouraged. Thanks!
Please return to your regularly scheduled discussions.
--
kernel, n.: A part of an operating system that preserves the
medieval traditions of sorcery and black art.
Danny
[-- Attachment #2: check_stack --]
[-- Type: text/x-perl, Size: 2011 bytes --]
#!/usr/bin/perl
# check_stack --- check for too deep stack depths; it most likely only
# only works for the linux kernel....
use 5.006;
use strict;
use warnings;
use Getopt::Std;
use lib "blib/lib";
use Disassemble::X86;
use vars qw ( $opt_d );
getopts ("d") and $#ARGV == 1 or die <<END_USAGE;
usage: $0 [-d] vmlinux System.map
-d debug ON
END_USAGE
# slurp up the whole object file
open OBJ, "<$ARGV[0]" or die "$0: can't read $ARGV[0]: $!\n";
my $slash_save = $/;
undef $/;
my $file = <OBJ>;
close OBJ;
$/ = $slash_save;
# init the disassembler
my $dis = Disassemble::X86->new (
start => 0xc0100000 - 0x1000, # text addr - file offset
pos => 0,
size => 32,
text => $file,
);
# you may change these as you see fit
# max_check is the maximum number of instructions to scan for the 'sub esp,...'
# before giving up
my $max_check = 10;
# stack_limit is the size that we'll consider worthy of reporting
my $stack_limit = 512;
# end of changables
# max_stack is the maximum stack size we saw
my $max_stack = 0;
# open System.map. It contains the address, type, and names of each function
# (among other things)
open MAP, "<$ARGV[1]" or die "$0: can't read $ARGV[1]: $!\n";
while (<MAP>) {
my ($addr, $type, $name) = split (' ', $_);
next if $name =~ /^\./; # we don't want names like '.yadda'
if ($type =~ /^[Tt]$/) { # we only want text symbols
print "looking at $name ($addr)\n" if $opt_d;
$dis->pos (hex ($addr));
for (my $i = 0; $i < $max_check && !$dis->at_end; $i++) {
my $op = $dis->disasm ();
printf "%04x %s\n", $dis->op_start (), $op if $opt_d;
next if (!defined $op);
if ($op =~ /sub esp,(0x[[:xdigit:]]+)/) {
my $stack = hex ($1);
$max_stack = $stack if $stack > $max_stack;
printf "check $name (stack %d)\n", $stack
if $stack >= $stack_limit;
last;
}
}
}
}
close MAP;
print "max single stack used is $max_stack\n";
exit 0;
# end check_stack
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: Functions with Large Stack Usage
2002-08-27 18:08 Functions with Large Stack Usage Danny Cox
@ 2002-08-28 3:56 ` Keith Owens
0 siblings, 0 replies; 2+ messages in thread
From: Keith Owens @ 2002-08-28 3:56 UTC (permalink / raw)
To: Linux Kernel List
On 27 Aug 2002 14:08:24 -0400,
Danny Cox <danscox@mindspring.com> wrote:
> After having read of the stack overflow "issues" awhile back, a couple
>of ideas gelled, with this script as a result. The script finds
>functions that use a large (changeable) amount of stack space. Note:
>it's heuristic, it's static, it only looks at compiled-in functions, and
>says nothing about the dynamic system. It DOES point out functions that
>may (MAY) need to be examined closer.
>...
> How it works: With Keith Owens' KDB patch, one may compile the kernel
>with frame pointers. With the Disassemble::X86 Perl module from CPAN
>(http://search.cpan.org/author/BOBMATH/Disassemble-X86-0.12/X86.pm),
>it's easy. It requires the vmlinux and System.map files, and for each
>function looks at the first 10 instructions for the 'sub esp,N'. The N
>is the number of bytes of stack used.
No need for frame pointers, or Perl. Run as
kernel.stack vmlinux $(/sbin/modprobe -l)
#!/bin/bash
#
# Run a compiled ix86 kernel and print large local stack usage.
#
# />:/{s/[<>:]*//g; h; } On lines that contain '>:' (headings like
# c0100000 <_stext>:), remove <, > and : and hold the line. Identifies
# the procedure and its start address.
#
# /subl\?.*\$0x[^,][^,][^,].*,%esp/{ Select lines containing
# subl\?...0x...,%esp but only if there are at least 3 digits between 0x and
# ,%esp. These are local stacks of at least 0x100 bytes.
#
# s/.*$0x\([^,]*\).*/\1/; Extract just the stack adjustment
# /^[89a-f].......$/d; Ignore line with 8 digit offsets that are
# negative. Some compilers adjust the stack on exit, seems to be related
# to goto statements
# G; Append the held line (procedure and start address).
# s/\(.*\)\n.* \(.*\)/\1 \2/; Remove the newline and procedure start
# address. Leaves just stack size and procedure name.
# p; }; Print stack size and procedure name.
#
# /subl\?.*%.*,%esp/{ Selects adjustment of %esp by register, dynamic
# arrays on stack.
# G; Append the held line (procedure and start address).
# s/\(.*\)\n\(.*\)/Dynamic \2 \1/; Reformat to "Dynamic", procedure
# start address, procedure name and the instruction that adjusts the
# stack, including its offset within the proc.
# p; }; Print the dynamic line.
#
#
# Leading spaces in the sed string are required.
#
objdump --disassemble "$@" | \
sed -ne '/>:/{s/[<>:]*//g; h; }
/subl\?.*\$0x[^,][^,][^,].*,%esp/{
s/.*\$0x\([^,]*\).*/\1/; /^[89a-f].......$/d; G; s/\(.*\)\n.* \(.*\)/\1 \2/; p; };
/subl\?.*%.*,%esp/{ G; s/\(.*\)\n\(.*\)/Dynamic \2 \1/; p; }; ' | \
sort
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2002-08-28 3:52 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-08-27 18:08 Functions with Large Stack Usage Danny Cox
2002-08-28 3:56 ` Keith Owens
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox