xfs
[Top] [All Lists]

Re: Large Stack Usage in One More Function

To: Danny Cox <danscox@xxxxxxxxxxxxxx>
Subject: Re: Large Stack Usage in One More Function
From: Keith Owens <kaos@xxxxxxx>
Date: Wed, 28 Aug 2002 11:28:23 +1000
Cc: XFS Mailing List <linux-xfs@xxxxxxxxxxx>
In-reply-to: Your message of "27 Aug 2002 12:58:01 -0400." <1030467482.1611.14.camel@wiley>
Sender: linux-xfs-bounce@xxxxxxxxxxx
On 27 Aug 2002 12:58:01 -0400, 
Danny Cox <danscox@xxxxxxxxxxxxxx> wrote:
>       After having read of the stack "issues" awhile back, and then having an
>idea or two gel in my head (it didn't hurt much ;-), I put them
>together, and found that xfs_ioctl() is using 752 bytes of stack.  I
>chose 512 as the number of bytes above which to complain about, and
>looking at the code, I'd guess that the var "vattr_t va" struct is the
>main culprit.
>
>       This is just a caution, and things may be just fine, of course.
>
>       The ideas were:
>
>       1) with the KDB patch, you can compile the kernel with frame pointers.
>       2) within the "function prelude", the frame pointer has N bytes
>subtracted from it.  This is the amount of stack that the function uses,
>plus some slop (perhaps).
>       3) there exists a module for Perl that can disassemble i386
>instructions.
>
>       So, I have a Perl script that will accept vmlinux and System.map
>arguments, and look at every function mentioned for the "sub esp,N"
>within the first 10 instructions after the function beginning.
>
>       It's a heuristic, it's static, it only looks at functions compiled in,
>and says nothing about the dynamic system, but can point out functions
>that use large amounts of stack.

There is a simpler way of doing it.  Script kernel.stack (below in
plain text, the new mailer on oss.sgi.com is stripping attachments).
Run as 'kernel.stack vmlinux $(/sbin/modprobe -l)'.  No need to compile
the kernel with frame pointers.  Now I have to go and fix all the large
kdb allocations :(.

#!/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 lines 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


<Prev in Thread] Current Thread [Next in Thread>