
                Microsoft Windows NT Call Profiler README File

                              March     06, 1992
                              September 22, 1992
                              February  22, 1993
                              April     27, 1994



1.  Description:
----------------

        Windows NT (32-bit) Call/Attributive Profiler (CAP) for x86, Mips, 
        and Alpha platforms.

        CAP is a general purpose profiling tool that can be used to measure
        the function call performance of .EXE's and .DLL's, (AKA modules),
        in a variety of ways.  The following measurement methods are
        supported:

            a)  Measuring calls from within an .EXE.

            b)  Measuring calls from within a .DLL.

            c)  Measuring calls from an .EXE to all of it's DLLs.

            d)  Measuring calls from one .DLL to all of its DLLs.

            e)  Measuring all the calls to specified .DLL's, from
                any .EXE or .DLL.

            f)  Any arbitrary combination of a) through e).

        CAP creates a call tree of all the functions called in the EXE(s)/
        DLL(s) being profiled.

        Profiling Data can be collected only for functions in C programs by
        using the attributed profiling hook provided by the Microsoft C
        compiler (compiling with the "-Gh" option).  Data is *NOT* collected
        for functions in assembler language programs.



2.  Profiling Files:
--------------------

        o  cap.ini       -- Call Profiler initialization file.
        o  cap.dll       -- Call Profiler DLL.
        o  cap.lib       -- Profiler library file containing profiling entry
                            points.
        o  capdump.exe   -- Dump utility for dumping/clearing profiling
                            data, and stopping profiling at any time.
        o  capsetup.exe  -- Allows attaching/detaching cap.dll to/from all
                            Windows applications.
        o  penter.lib    -- An empty library containing a dummy CAP entry point.
                            This can be used instead of CAP.lib to link with an
                            already CAP ready executable object modules
                            (recompiled with the -Gh option) so the application
                            can run without recompiling and without any of the
                            CAP overheads.
        o  sol.end       -- A sample CAP data file generated by a sample
                            profile run of sol.exe.
        o  readme        -- Call Profiler README document (this file).



3.  Using the Call Profiler:
----------------------------



        o  Place a copy of CAP.INI in one of the following area where it
           suits your need:
           - the CURRENT directory
           - the Windows directory (ie: c:\windows\cap.ini)
           - the root of the current drive (\cap.ini)
           - the root dir of C: drive (c:\cap.ini)

           list all the DLL/EXE images to be profiled as follows:

           (Note:  CAP.INI and all its three section headers must exist but the
            sections could be left blank)

           [EXES]
           Name of applications to be profiled. Each name should be on a
           new line.

           [PATCH IMPORTS]
           List of DLLs/EXEs to be profiled for all of their imported entries.
           Each name should be on a new line.

           [PATCH CALLERS]
           List of DLLs to be profiled for their exported entries if called
           from the applications (listed in the [EXE] section) or any of their
           DLLs.  Each name should be on a new line.

           [NAME LENGTH]
           This is an optional section allowing to specify the maximum number of
           characters to be printed for the routine name in the output data
           files.  If the value is not specified or 0, default length of 40 is
           used.  Length can be any value between 20 and 2048.

           [CHRONO FUNCS]
           List of modules and corresponding functions that start the dump
           of the chronological listing.  For example, if "test=SomeFunc" is
           listed under this section then all functions that are called
           inside of test!SomeFunc... will be listed until the call depth
           is less than or equal to the depth of the listed function.

           [EXCLUDE FUNCS]
           List of modules and corresponding functions that will be excluded
           from the profiling process.  The [call _penter] at the beginning
           of the function will be NOPed.  But if these functions call
           some other functions and if these children functions are not listed
           under this section, they will still be included in the profiling
           process.  To correctly take a function out of the profiling
           process, him and his children must all be included under this
           section.  If not, the timing of the Excluded function will be
           included with its parent routine while the timing of its children
           routine will still be computed separately.

           [OUTPUT FILE]
           filename=xxxxx
           This option allows the user to specify a different drive for the
           output listing.  This file can be over the net somewhere or just
           a different name than xxxx.END or xxxx.CAP.  For example:
                filename=c:\results\explorer\explorer.cap            or
                filename=\\Results\CAP\explorer\explorer.pro

           [CAP FLAGS]
           - profile
             "on" or "off".  Turn on or off profiling initially without
             altering the code.
           - dumpbinary
             "on" or "off".  This is to allow the dumping of the data in binary form,
             not in the regular text form.  This feature is there to allow faster
             dumping and require less space.  A program called CAPRPT will go in and
             produce the listing from this data.  CAPRPT is still under development.
           - capthread
             "on" or "off".  If on, this switch will start the 3 threads that will
             interact with CAPDUMP to Clear, Start and Stop the collection of data.
             This is made into an option so if the user does not need CAPDUMP, he/she
             does not have to start 3 additional threads everytime CAP is initialized.
             This is quite expensive when profiling a number of processes at the same
             time.
           - loadlibrary
             "on" or "off".  If on, CAP will intercept all LoadLibrary calls from the
             profiled binary and correctly initializes its symbol table.
           - setjump
             "on" or "off".  If on, CAP will also intercept longjmp instructions and
             handled it accordingly.
           - undecoratename
             "on" or "off".  Turn on or off the undecoration of function
             names.
           - excelaware
             "on" or "off". Turn on or off the addition of delimiters so
             the output listing can be imported into Excel.
           - regular dump
             "on" or "off".  Turn on or off the regular data that CAP dumps out.
             This is to shorten the output listing if you are only interested in
             the chronological listings.
           - chronocollect
             "on" or "off".  Turn on or off the collection of the chronological
             listing of the functions. This could be very lengthy.
           - chronodump
             "on" or "off".  Turn on or off the output for the chrono listing.
             This switch is independent of [chronocollect] since sometimes you
             just want to turn off the dumping but leaving the collection alone.
           - slowsymbols
             "on" or "off".  Turn on or off exhaustive lookup of symbols.  If
             off, addresses for which symbols cannot be quickly found (e.g.
             static symbols) are printed as absolute addresses versus a symbol
             plus offset in the on case.

        o  Attach CAP.DLL to the application process. This can be done in two
           ways:

           1)  Recompile your EXE/DLL using the "-Gh" and "-Zd" compiler
               options.  (NOTE - on Mips platform, use "-Od" to disable
               compiler optimization.)

               Link it with CAP.LIB using the "-debugtype:coff" and
               "-debug:mapped,partial" linker options.

               This method will cause all the C functions in the recompiled
               sources to be profiled.

               NOTE:-  If symbols have been removed from your exe
               or dll, Cap will try to locate the symbols files (DBG
               files) using the path as specified in the environment
               variable "_nt_symbol_path".
               E.G. if the DBG file of your exe is in c:\symbols\exe, set
               _nt_symbol_path to c:\symbols.

           2)  Run CapSetup.exe to attach CAP.DLL to all Windows applications.
               Note that only those EXEs listed in the [EXES] section of
               CAP.INI will be profiled.  Overhead for the non-profiled
               applications is minimal.  See section 8, "Using CapSetup",
               for CapSetup.exe usage.  You need to have Administrative
               privileges in order to run CapSetup.

               *** Please be extremely careful with this option since turning
               *** it on could resulted in the system being totally thrashed
               *** if CAP.DLL could not run correctly.  Thus causing the
               *** profiled binary to fail to load also.  And if the binary
               *** is as important as WINLOGON, then the only thing to do
               *** is to reload NT or use a dummy cap.dll or remove the 
               *** CAP.INI file.


        o  Place CAP.DLL in your SYSTEM directory (i.e. ..\nt\system32).

        o  Run your applications.

        o  All the applications specified in the [EXES] section of the CAP.INI
           will be profiled.

        o  Exit the application to dump the profiling data, or run CapDump.exe
           to dump the data.  See section 6 "Profiling Data" for details.



4.  Examples for Supported Measurement Methods:
----------------------------------------------

        Suppose we have Windows .EXE's called ZOOMAN and HUNTED, and .DLLs
        called ELEPHANT, MONKEY, SNAKE, WATER, and FOOD.  Let's assume the
        following intercall dependencies exist:

        zooman.exe
            - water.dll
            - food.dll

        hunted.exe
            - elephant.dll
                -- water.dll
                -- food.dll
            - monkey.dll
                -- water.dll
                -- food.dll
            - snake.dll



        a) Measuring calls from within ZOOMAN.EXE:

            o Recompile ZOOMAN and link it with CAP.LIB as described in
              section 3.

            o Setup CAP.INI as follows:

              [EXES]
              zooman.exe

              [PATCH IMPORTS]

              [PATCH CALLERS]

              [NAME LENGTH]
              60

            o All the C functions in ZOOMAN.EXE will be profiled by CAP.



        b) Measuring calls from within WATER.DLL:

            o Recompile WATER and link it with CAP.LIB as described in
              section 3.

            o Setup CAP.INI as follows:

              [EXES]
              zooman.exe
              hunted.exe

              [PATCH IMPORTS]

              [PATCH CALLERS]

              [NAME LENGTH]

            o Both ZOOMAN.EXE and HUNTED.EXE will be profiled for all the
              C functions within WATER.DLL.



         c) Measuring calls from HUNTED.EXE to it's DLLs:

            o Run CapSetup.exe to attach cap.dll to all Windows Applications,
              and reboot the system.

            o Setup CAP.INI as follows:

              [EXES]
              hunted.exe

              [PATCH IMPORTS]
              hunted.exe

              [PATCH CALLERS]

              [NAME LENGTH]

            o All the calls from HUNTED.EXE to ELEPHANT.DLL, MONKEY.DLL,
              and SNAKE.DLL will be profiled.  These are all the C functions
              exported by ELEPHANT, MONKEY, and SNAKE DLLs which are used
              by HUNTED.exe.



         d) Measuring calls from ELEPHANT.DLL and MONKEY.DLL to their DLLs:

            o Run CapSetup.exe to attach cap.dll to all Windows Applications,
              and reboot the system.

            o Setup CAP.INI as follows:

              [EXES]
              hunted.exe

              [PATCH IMPORTS]
              elephant.dll
              monkey.dll

              [PATCH CALLERS]

              [NAME LENGTH]

            o All calls from ELEPHANT.DLL and MONKEY.DLL to WATER.DLL and
              FOOD.DLL will be measured.  These are all the C functions
              exported by WATER and FOOD DLLs which are used by either
              ELEPHANT.DLL or MONKEY.DLL.



         e) Measuring all the calls to FOOD.DLL:

            o Run CapSetup.exe to attach cap.dll to all Windows Applications,
              and reboot the system.

            o Setup CAP.INI as follows:

              [EXES]
              zooman.exe
              hunted.exe

              [PATCH IMPORTS]

              [PATCH CALLERS]
              food.dll

              [NAME LENGTH]

            o Both ZOOMAN.EXE and HUNTED.EXE will be profiled separately for
              all the calls to FOOD.DLL.  For ZOOMAN.EXE, these are all the
              C functions exported by FOOD.DLL which are used by ZOOMAN.EXE.
              And for HUNTED.EXE these are all the C functions exported by
              FODD.DLL which are used by either ELEPAHNT.DLL or MONKEY.DLL.


         f) Any arbitrary combination of a) through e):

            a+c) Measuring calls from within ZOOMAN.EXE and calls to it's DLLs:

            o Recompile ZOOMAN and link it with CAP.LIB as described in
              section 3.

            o Setup CAP.INI as follows:

              [EXES]
              zooman.exe

              [PATCH IMPORTS]
              zooman.exe

              [PATCH CALLERS]

              [NAME LENGTH]


            c+d) Measuring calls from HUNTED.EXE to it's DLLs and calls from
                 ELEPHANT and MONKEY DLLs to their DLLs:

            o Run CapSetup.exe to attach cap.dll to all Windows Applications,
              and reboot the system.

            o Setup CAP.INI as follows:

              [EXES]
              hunted.exe

              [PATCH IMPORTS]
              hunted.exe
              elephant.dll
              monkey.dll

              [PATCH CALLERS]

              [NAME LENGTH]


            a+c+d) Measuring calls from within HUNTED.EXE and calls to its DLLs
                   plus calls from ELEPHANT and MONKEY DLLs to their DLLs:

            o Recompile HUNTED and link it with CAP.LIB as described in
              section 3.

            o Setup CAP.INI as follows:

              [EXES]
              hunted.exe

              [PATCH IMPORTS]
              hunted.exe
              elephant.dll
              monkey.dll

              [PATCH CALLERS]

              [NAME LENGTH]


            b+d) Measuring calls from within ELEPHANT.DLL and calls to its DLLs:

            o Recompile ELEPHANT and link it with CAP.LIB as described in
              section 3.

            o Setup CAP.INI as follows:

              [EXES]
              hunted.exe

              [PATCH IMPORTS]
              elephant.dll

              [PATCH CALLERS]

              [NAME LENGTH]


              * * * * * * * * * * * * *
         * * *  R E S T R I C T I O N  * * *
              * * * * * * * * * * * * *

         Do NOT measure calls within a DLL if the DLL's exported functions
         are being measured from another EXE/DLL.  The following example shows
         this incorrect combination which should be avoided:

            x) Measuring calls from ZOOMAN.EXE to its DLLs and calls within
               WATER.DLL:

            o Recompile WATER and link it with CAP.LIB as described in
              section 3.

            o Setup CAP.INI as follows:

              [EXES]
              zooman.exe

              [PATCH IMPORTS]
              zooman.exe

              [PATCH CALLERS]

              [NAME LENGTH]

            o Note that in addition to measuring all C functions (including the
              exported routines) within WATER.DLL, all the C functions exported
              by WATER.DLL which are used by ZOOMAN.EXE are measured.  This
              means that the same function within WATER.DLL will be measured
              twice. These types of scenarios are not supported and will result
              in unexpected behavior.




5.  Exported Routines:
----------------------

        The exported entry points listed below can be used to control
        profiling certain sections of code.  They can be combined with
        any of the supported measurement methods mentioned above.

        o  StartCAP() : Clears profiling data & starts profiling
        o  StopCAP()  : Stops profiling
        o  DumpCAP()  : Dumps data for the current CAP.DLL instance

        A typical example (foo.exe):

            StartCAP();         // Clear existing profiling data and restart
                                // profiling.
            ..
            ..                  // application's code
            ..

            StopCAP();          // Stop profiling without dumping data.
            DumpCAP();          // Dump profiling data to FOO.CAP file.

        Prototypes for these routines are:

        extern void _stdcall StartCAP(void);
        extern void _stdcall StopCAP(void);
        extern void _stdcall DumpCAP(void);


6.  Profiling Data:
-------------------

        o  Profiling data can be captured in three ways:

           1)  Upon termination of the application profiling data is dumped
               into a text file using the application name with .END
               extension.

           2)  Using the dump utility, CapDump.exe, profiling data can be
               dumped at any time.  Application name with .CAP extension will
               be the data file name.  See section 7 "Using CapDump" for more
               details.

           3)  Using exported routine DumpCAP().  Application name with .CAP
               extension will be the data file name.


        o  Data files are created in the same directory as the application
           that is being profiled.

        o  Data is appended to data files with each data dump.

        o  A separate call tree is generated for each thread in the process
           context.  Different sections in the data file indicates data for
           different threads in the process.

        o  The following data is dumped:

           - Call depth in the tree
           - Function name
           - Number of calls
           - Total time for the function+callees
           - Time per call for the function+callees
           - Total time of the function only
           - Time per call of the function only
           - First time (function+callees)
           - Minimum time (function+callees)
           - Maximum time (function+callees)

        o  See SOL.END as a sample output file.



7.  Using CapDump:
------------------

        o  CapDump.exe can be used to stop profiling and clear/dump
           profiling data for all the applications being profiled, at
           any time.

        o  The following options are available via CapDump.exe:

              - Stop : Stops profiling (applications continue to run).

              - Clear and Restart : Clears any existing profiling data and
                                    restarts profiling.

              - Dump and Stop : Dumps any existing profiling data and stops
                                profiling (applications continue to run).

        o  Data is dumped to a text file using the profiling applications name
           with .CAP extension. All fields are tab separated.   Data is
           appended to data files with each dump.

        o  If calls are being profiled when data clearing is requested,
           the time of clearing is used as the starting time for those
           calls.

        o  A log file, capdump.log, is generated when capdump.exe is run.  It
           will contain any errors that might occur during capdump.exe operation
           and for normal error free operation, capdump.log will be empty.



8.  Using CapSetup:
-------------------

        Usage:  CapSetup  -A | -D

          -A    Attaches CAP.dll to all Windows applications
          -D    Detaches CAP.dll from all Windows applications

          Notes:  1)  Administrative privileges are required in order to run
                      CapSetup.
                  2)  System needs to be rebooted in order for the change to
                      take effect.

          *** Please be extremely careful with this option since turning
          *** it on could resulted in the system being totally thrashed
          *** if CAP.DLL could not run correctly.  Thus causing the
          *** profiled binary to fail to load also.  And if the binary
          *** is as important as WINLOGON, then the only thing to do
          *** is to reload NT or use a dummy cap.dll, or remove
          *** the CAP.INI file.

9.  Caveats:
------------

        o  Mips and Alpha Cap - if a routine being profiled is within try-except 
           block and it crashes,  the stack will NOT unwind.  This is because 
           there is no prolog code in the Cap penter to support this.

        o  For Mips only - Mips Cap cannot profile static functions. 

        o  If symbols are not available in an EXE/DLL that is being profiled,
           ??? is displayed as the function name.

        o  Non-local GOTOs (i.e. setjmp/longjmp calls) are not currently
           supported.  Profiling an application containing any non-local GOTOs
           will result in unexpected results.

        o  Profiling data in *NOT* collected for functions in assembler
           language programs.

        o  Paging file size will increase while profiling.

        o  For Alpha only - setjump, loadlibrary, and Exclude Funcs are not
           implemented in this release.

        o  It may take a long time when cap is dumping data to the
           cap file.  In some cases, it may take up to 30 minutes,
           depending on how many symbols and the level of nesting
           calls.

        o  If you are using GDI calls, you may want to add GdiSetBatchLimit(1)
           for each thread before you re-compile with cap.lib. This is to disable
           batching so each GDI call will be performed and profiled correctly.

** END OF README **
