SSP(1) CYGWIN SSP(1)NAME
- Single-step profile COMMAND
SYNOPSISssp [options] low_pc high_pc command...
OPTIONS-c, --console-trace
trace every EIP value to the console. *Lots* slower.
-d, --disable
disable single-stepping by default; use OutputDebugString ("ssp
on") to enable stepping
-e, --enable
enable single-stepping by default; use OutputDebugString ("ssp
off") to disable stepping
-h, --help
output usage information and exit
-l, --dll
enable dll profiling. A chart of relative DLL usage is produced
after the run.
-s, --sub-threads
trace sub-threads too. Dangerous if you have race conditions.
-t, --trace-eip
trace every EIP value to a file TRACE.SSP. This gets big
*fast*.
-v, --verbose
output verbose messages about debug events.
-V, --version
output version information and exit
Example: ssp 0x401000 0x403000 hello.exe
DESCRIPTION
SSP - The Single Step Profiler
Original Author: DJ Delorie
The SSP is a program that uses the Win32 debug API to run a program
one ASM instruction at a time. It records the location of each
instruction used, how many times that instruction is used, and all
function calls. The results are saved in a format that is usable by
the profiling program gprof, although gprof will claim the values are
seconds, they really are instruction counts. More on that later.
Because the SSP was originally designed to profile the cygwin DLL, it
does not automatically select a block of code to report statistics on.
You must specify the range of memory addresses to keep track of manu‐
ally, but it's not hard to figure out what to specify. Use the "obj‐
dump" program to determine the bounds of the target's ".text" section.
Let's say we're profiling cygwin1.dll. Make sure you've built it with
debug symbols (else gprof won't run) and run objdump like this:
$ objdump -h cygwin1.dll
It will print a report like this:
cygwin1.dll: file format pei-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0007ea00 61001000 61001000 00000400 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE, DATA
1 .data 00008000 61080000 61080000 0007ee00 2**2
CONTENTS, ALLOC, LOAD, DATA
. . .
The only information we're concerned with are the VMA of the .text
section and the VMA of the section after it (sections are usually con‐
tiguous; you can also add the Size to the VMA to get the end address).
In this case, the VMA is 0x61001000 and the ending address is either
0x61080000 (start of .data method) or 0x0x6107fa00 (VMA+Size method).
There are two basic ways to use SSP - either profiling a whole pro‐
gram, or selectively profiling parts of the program.
To profile a whole program, just run ssp without options. By
default, it will step the whole program. Here's a simple example,
using the numbers above:
$ ssp 0x61001000 0x61080000 hello.exe
This will step the whole program. It will take at least 8 minutes on a
PII/300 (yes, really). When it's done, it will create a file called
"gmon.out". You can turn this data file into a readable report with
gprof:
$ gprof -b cygwin1.dll
The "-b" means 'skip the help pages'. You can omit this until you're
familiar with the report layout. The gprof documentation explains a
lot about this report, but ssp changes a few things. For example,
the first part of the report reports the amount of time spent in each
function, like this:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
10.02 231.22 72.43 46 1574.57 1574.57 strcspn
7.95 288.70 57.48 130 442.15 442.15 strncasematch
The "seconds" columns are really CPU opcodes, 1/100 second per opcode.
So, "231.22" above means 23,122 opcodes. The ms/call values are 10x
too big; 1574.57 means 157.457 opcodes per call. Similar adjustments
need to be made for the "self" and "children" columns in the second
part of the report.
OK, so now we've got a huge report that took a long time to generate,
and we've identified a spot we want to work on optimizing. Let's say
it's the time() function. We can use SSP to selectively profile this
function by using OutputDebugString() to control SSP from within the
program. Here's a sample program:
#include <windows.h>
main()
{
time_t t;
OutputDebugString("ssp on");
time(&t);
OutputDebugString("ssp off");
}
Then, add the -d option to ssp to default to *disabling* profiling.
The program will run at full speed until the first OutputDebugString,
then step until the second. You can then use gprof (as usual) to see
the performance profile for just that portion of the program's execu‐
tion.
There are many options to ssp. Since step-profiling makes your pro‐
gram run about 1,000 times slower than normal, it's best to understand
all the options so that you can narrow down the parts of your program
you need to single-step.
-v - verbose. This prints messages about threads starting and stop‐
ping, OutputDebugString calls, DLLs loading, etc.
-t and -c - tracing. With -t, *every* step's address is written to
the file "trace.ssp". This can be used to help debug functions, since
it can trace multiple threads. Clever use of scripts can match
addresses with disassembled opcodes if needed. Warning: creates *huge*
files, very quickly. -c prints each address to the console, useful
for debugging key chunks of assembler. Use addr2line -C -f -s -e
foo.exe < trace.ssp > lines.ssp and then perl cvttrace to convert to
symbolic traces.
-s - subthreads. Usually, you only need to trace the main thread,
but sometimes you need to trace all threads, so this enables that. It's
also needed when you want to profile a function that only a subthread
calls. However, using OutputDebugString automatically enables profil‐
ing on the thread that called it, not the main thread.
-l - dll profiling. Generates a pretty table of how much time was
spent in each dll the program used. No sense optimizing a function in
your program if most of the time is spent in the DLL. I usually use the
-v, -s, and -l options:
$ ssp-v-s-l-d 0x61001000 0x61080000 hello.exe
COPYRIGHT
Cygwin is Copyright (C) 1995-2010 Red Hat, Inc.
Cygwin is Free software; for complete licensing information, refer to:
http://cygwin.com/licensing.html
SEE ALSO
The full documentation to the Cygwin API is maintained on the web at:
http://cygwin.com/cygwin-api/cygwin-api.html
The website is updated more frequently than the man pages and should be
considered the authoritative source of information.
April 2010 SSP(1)