FunctionCheck V1.2 (Y. Perret, January 2000)


I.   Description
II.  Bugs
III. The 'fncdump' program
IV.  Example
V.   Internal description
VI.  Licence
VII. Contact
VIII.Changes
IX.  ToDo list
X.   The 'fncaverage' program

I.   Description
----------------

FncCheck is a library which generates profiles for C/C++ programs.
A profile is a list of informations about your functions, such as
time spend in functions, number of calls and other things.

To read more precise informations, please use the 'fncdump.info'
file or the THML version, respectively in doc/ and doc/html/ dirs.

In order to use FncCheck, you have to compile your .o files
with '-finstrument-functions -g' switches (gcc V2.95.2 and higher).
You have then to link your executable with the library 'libfnccheck.so'
or the object 'fnccheck.o'.
Note: if you use 'fnccheck.o', you have to add '-lm' flag. 
Note: the '-g' switch is not an obligation. But without it,
      you will not be able to use '-func+' and '-calls+' options.
See the test/ dir for an example of compilation.

Once compiled, make a complete execution of your program.
It generates a 'fnccheck.out' file in the current directory
(the exact name of the file is displayed at the end of execution).
If your program performs 'forks()', each of your childs will
generates a 'fnccheck.out_PID_OF_CHILD' for its execution.

In order to see profile of your executable, use 'fncdump' program
(see below for details on dumps).


Controls available:
The library uses a table for functions name and a stack to store
functions calls. For speed reasons, these tables are allocated
once at the beginning of the program (at 1024 and 1000000 resp.).
It is possible to change these size by changing shell varaiables:

* FNCCHK_STOP      : if set, the lib is desactivated.
* FNCCHK_STACKSIZE : the the size of the stack.
* FNCCHK_NBFUNC    : set the size of the functions table.
* FNCCHK_OUTFILE   : name of output file (default: './fnccheck.out').
* FNCCHK_DYNAMIC   : if set, allows to increase tables size if
    needed. Can introduce bias in times computations.
* FNCCHK_NOCHILD   : if set, childs of the process are not dumped
    to file at all.
* FNCCHK_TIME      : set the time mode:
                "ext" -> external time (gettimeofday),
                "cpu" -> CPU time of process (clock())
    Default value is "ext".
* FNCCHK_DEBUG     : ORed values of debug options. Values are:
    2: display collisions for the hash table at the end
    4: details on each fnccheck functions
    8: details on treatments

Note: FNCCHK_DEBUG has no effect if the lib is not compiled
  with debug mode ('make dfnccheck' instead of 'make fnccheck').

Note: the FNCCHK_PID variable is removed. Now, the default behavior
  of 'fnccheck' is to generates 'fnccheck.out' file for the
  starting process, and to generates 'fnccheck.out_PID' for childs.

WARNING: a hash table is used to store functions during execution.
Its size is computed using the initial size of the
functions table. It is NOT (at this time) reallocated if functions
table size is increased. Number of colisions in the hash-table
will so increase too.

Any invalid value make default values used instead.


II.  BUGS
---------

No one known for V1.2 at this time.

-----------------
|III.  fncdump  |
-----------------

'fncdump' is the program given with FncCheck which display profiles
(it was named 'dump' in old versions).

For each function is displayed:

* the cycles detected:

List of detected cycles during execution (with -cycles option).

* the flat profile:

- its total time (time between enter and exit of the function)
- its local time (total time minus the time spend in child
       referenced functions)
- corresponding '%' (regards to the total execution time)
- the number of calls to the function
- the average time per call (total time divided by # of calls)

* MIN/MAX:

List of min and max times for each functions.

* functions details:

If requested (-func-details), display the list of functions
with their file and line number (must be compiled with '-g' option).

* the call-graph:

list of calls per function. For each function, the
list of every functions which call it.
Note: '-calls' option modify this list. For each function the
list of the functions it call.




Other informations are displayed:

- the executable name
- the execution total time
- the kind of time used (EXT, CPU or SYS)
- the number of 'realloc' performed (if allowed)
- the final stack size
- the number of functions
- the number of non-displayed functions, due to option -no-unresolved
- the number of non-displayed functions, due to option -no-spontaneous
- the list of MIN and MAX time spend in each functions


* Here is the --help of fncdump:

Usage: fncdump exec [opts]
   or: fncdump -avg
Opts:  -sfile f        : use 'f' as stat file instead of 'fnccheck.out'
       -sort n         : sort mode. See at the end for details
       +sort n         : sort mode (reverse). See at the end for details
       -no-spontaneous : dont print spontaneous called functions (dont apply to main)
       -no-unresolved  : dont print unresolved symbols
       -calls          : show 'called' functions instead of 'called by'
       +calls          : show 'called' functions AND 'called by'
       -no-minmax      : dont display MIN/MAX time for functions
       -nm             : use 'nm' instead of 'libbfd'(1) to extract names
       -addr2line      : use 'nm' instead of 'libbfd'(1) to extract names
       -func-details   : add file/line for functions (not with '-nm')
       -call-details   : add file/line for function calls (not with '-nm')
       -fullname       : use full pathname for file/line info
       -only <lst>     : just use functions that are in the comma separated list
       -not <lst>      : dont use functions that are in the comma separated list       -propagate      : -only/-not is applied to childs
       -rpropagate     : -only/-not is applied to callers
       -propagate      : -only/-not is applied to childs
       -real-maxtime   : use total execution time of displayed functions rather
                         than total exec. time of all functions.
    -sum-profile a b c : sum profile files a and b into c (- means stdout)
       --help          : this message
       --version       : fnccheck/dump version
       --misc          : author/contact/bugs
       --details       : explanations about displayed informations
Sort types:
    1:  sorted by 'Local time'
    2:  sorted by 'Total time'
    3:  sorted by 'Call number'
    4:  sorted by 'Function name'
    5:  sorted by 'No sort'

The -avg usage gives you the average time spend
  in FncCheck treatments per each of your function.
Note: the '-avg' switch now calls the 'fncaverage' program.
You can use it directly.

* 'exec' is the executable name.
* '-sfile f' use 'f' stat. file instead of 'fnccheck.out'.
* '+/-sort n' indicate the kind of sort (ascending/descending).
* '-avg' display the average time spend in the library for each
      enter/exit of functions.
* '-no-spontaneous' dont display spontaneous functions. Spontaneous
      functions are functions called by no one (dont apply to main).
* '-no-unresolved' dont display functions with unresolved symbols.
      (this can append if you use optimization options in gcc, or
      using static constructors in C++).
* '-calls' display 'called', instead 'called by'.
* '+calls' display both 'called' and 'called by'.
* '-no-minmax' remove MIN/MAX times displaying.
* '-nm' force the use of 'nm' to extract symbol names. Using this
    option, you will not be able to use '-func-details' and '-call-details'
* '-addr2line' force the use of 'addr2line' to extract symbol names,
  instead of 'libbfd' from GNU binutils (if compiled with BFD).
* '-only' specify a list of functions name. Only these functions
    are considered in the output stats.
* '-not' specify a list of functions name. These functions
    are removed from the output stats.
* '-propagate' is used with '-only' and '-not'. It propagates
    functions to use or to remove using call-tree (a child
    of a referenced function is treated the same).
* '-rpropagate' is the same than '-propagate', but the direction
    of propagation is "callers" instead of "childs".
* '-func-details' displays a list of all functions with the file
    and the line from which they come from.
* '-call-details' displays file and line of each call, in the
    'called by' or 'calls' list.
* '-real-maxtime' compute total execution time using the displayed
    list of functions instead of the total list of functions. It means
    that if you remove 'main' from the displayed list, the total
    execution time will be smaller than the real execution time of
    the program. Usefull when studying sub-parts of a program.
* '-sum-profile' read the two profile files 'a' and 'b' and generates
    a new profile file called 'c' which is the sum of the stats
    from the two previous files. Using '-' for 'c' means that the
    new profile is send into stdout. 'a' and 'b' are closed BEFORE
    'c' is opened, it is so possible to overwrite one of them by using
    the same name for 'c' and 'a' or 'b'.
    WARNING: if you sum two files from different programs or different
    compilations, generated stats will have few validity...


IV.  Example
------------

> gcc -c foo.c -finstrument-functions -g
> gcc -o foo foo.o -lfnccheck

(or   gcc -o foo foo.c -finstrument-functions -g -lfnccheck)

> foo
FunctionCheck: starting (V1.2 by Hexasoft).
FunctionCheck: all done (sfile: ./fnccheck.out).

Dump display:

> fncdump foo


FunctionChecker V1.2 for gcc (by Y. Perret)
Running profile data file version number 1.1.5

Cycles during execution:

1: Simple recursion:
  'recurs' calls itself.
  Total time for this function: 0.000103

2: Cycle:
  cycle from 'recurs_a' to 'recurs_b'
  Total time for this cycle: 5.348654

3: Simple recursion:
  'recurs_1s' calls itself.
  Total time for this function: 8.078811


General information:

Profile for 'foo'
Total execution time: 16.384126
Times computed using real clock time.
Number of realloc performed: 0
Unresolved functions not shown    : 0
Spontaneous functions not shown   : 0
Hidden functions due to -not/-only: 0
Final stack size used: 33
Number of function(s): 10

Flat profile:

|      local      |      total      |          |           |
|      sec. |  %  |      sec. |  %  | calls    |t. sec/call| name
|-----------|-----|-----------|-----|----------|-----------|--------
|   0.000048|  0.0|  16.384126|100.0|         1|  16.384126| main
|   4.038762| 24.7|   8.078811| 49.3|         4|   2.019703| recurs_1s
|   2.677678| 16.3|   5.348654| 32.6|         4|   1.337163| recurs_a
|   2.670976| 16.3|   4.679084| 28.6|         4|   1.169771| recurs_b
|   4.040041| 24.7|   4.040041| 24.7|         4|   1.010010| s1
|   2.956495| 18.0|   2.956495| 18.0|         1|   2.956495| test
|   0.000055|  0.0|   0.000103|  0.0|        32|   0.000003| recurs
|   0.000009|  0.0|   0.000013|  0.0|         1|   0.000013| f3
|   0.000004|  0.0|   0.000004|  0.0|         3|   0.000001| f1
|   0.000002|  0.0|   0.000002|  0.0|         1|   0.000002| small

MIN/MAX total time list:

|indx|     MIN     |     MAX     |name
|----|-------------|-------------|-----
|   0|    16.384126|    16.384126| main
|   1|     2.019944|     8.078811| recurs_1s
|   2|     1.340897|     5.348654| recurs_a
|   3|     0.666023|     4.679084| recurs_b
|   4|     1.009985|     1.010051| s1
|   5|     2.956495|     2.956495| test
|   6|     0.000002|     0.000103| recurs
|   7|     0.000013|     0.000013| f3
|   8|     0.000001|     0.000002| f1
|   9|     0.000002|     0.000002| small

Call-graph:

'main' [0] (essai.c:128) spontaneously called.

'recurs_1s' [1] (essai.c:56) called by:
   [0](essai.c:133),
   [1](essai.c:61),

'recurs_a' [2] (essai.c:68) called by:
   [0](essai.c:131),
   [3](essai.c:94),

'recurs_b' [3] (essai.c:82) called by:
   [2](essai.c:78),

's1' [4] (essai.c:16) called by:
   [1](essai.c:58),

'test' [5] (essai.c:121) called by:
   [0](essai.c:137),

'recurs' [6] (essai.c:48) called by:
   [0](essai.c:129),
   [6](essai.c:51),

'f3' [7] (essai.c:40) called by:
   [0](essai.c:138),

'f1' [8] (essai.c:22) called by:
   [7](essai.c:41),

'small' [9] (essai.c:113) called by:
   [0](essai.c:139),


V.  Internal representation
---------------------------

FncCheck uses 'nm' command to extract symbol names from functions addresses.
If 'nm' is not accessible, or if the symbol is not in the symbol table,
the functions name are replaced by their address in hexadecimal.
This can append:
- if executable name given to 'fncdump' is wrong (bad name, it have been
     compiled again after stat. generation...)
- if you use optimization options in gcc, and perhaps debug options (-pg...)
- if you use constructor in C++, which dont appear in symbol table but
     are treated as functions by gcc.

CHANGES:
Since V1.1.3, FncCheck uses 'addr2line' instead of 'nm' (but you can
still use 'nm' with '-nm' option).
This implies new features such as '-calls-details' and '-func-details'.

CHANGES:
Since V1.1.4, FncCheck uses 'libbfd' (from GNU binutils) to extract
function names from symbol addresses.
But you can still use 'addr2line' with '-addr2line' option,
or 'nm' using '-nm' option.
If 'bfd' (and 'iberty') libraries are not available on your system,
you can compile 'fncdump' without 'bfd' using the target 'fncdump_nobfd'.
In this case only 'nm' and 'addr2line' (default) approaches remain.


VI.  Licence
------------

GPL.
See COPYING for the GPL licence.
See COPYING.LIB if you intend to link the 'libfnccheck.so'
library to a proprietary program (which is requested to perform
profiling).


VII. Contact
------------

Author: Yannick Perret (Hexasoft)
EMail:  yperret@ligim.univ-lyon1.fr
HTTP:   http://www710.univ-lyon1.fr/~yperret/profiler.html

For bugs report, send mail to 'yperret@ligim.univ-lyon1.fr'


VIII. Changes
-------------
Thank to: Doolittle, Peter Osterlund, Karl Günter Wünsch,
          Petter Reinholdtsen, Yotam Medini,
for their contribution, bugs report, patches, suggestions...


Changes from 1.1.5 to 1.2:

* add option '-call-graph' which outputs the profiled program
    call-graph, using VCG format (a call-graph displayer under
    UNIX/Linux [and other]). Tested: OK.
* adding a doc/ dir. Adding a .texi file with the fnccheck/fncdump
    documentation in it. Adding a fncdump.info file (generated
    using fncdump.texi and makeinfo). Adding a doc/html/ dir,
    with an HTML doc in it (using fncdump.texi and texi2html).
* adding '-cycles' option. Displays the detected recursions
    and cycles (non-direct recursions) in the program. For each,
    display starting/ending function of the cycle and the total
    time spend in the cycle.
* add "titles" to parts of the 'fncdump''s output
    (i.e "General information:", "Flat profile:", "Call-graph:"...).
* create a 'fncinteract.h' header, with corresponding functions
    in 'fnccheck' lib. It adds some functions to interact with
    'fnccheck' lib during execution. The two main functions are
    'fnccheck_stop_profile()' and 'fnccheck_start_profile()'
    which allow the program to stop or re-start the profile
    treatments. Useful if you want to profile only a small part
    of your program.  ** Not stable **.
    Note: by default, main() is always part of the profiled functions
      (because you always enter main() before doing anything). It
      is possible to start your program 'as if' 'fnccheck_stop_profile()'
      was called before by using FNCCHK_SUSPEND variable.
    Note bis: if you desactivate profile before entering a function,
      and you re-activate it before leaving from this function, the
      'fnccheck' library will see an exit from a never-entering
      (for it) function. I dont know what can happend in this case
      (but a priori something bad :o)
* remove FNCCHK_PID variable. Now fnccheck creates a 'fnccheck.out'
    file for processes, instead of it is a child process, in which
    case a 'fnccheck.out_PID' is generated. It is possible to
    prevent childs to generate dump file by using FNCCHK_NOCHILD
    shell variable.
* change in the way 'total execution time' is performed.
* add '-sum-profile' which allows to add the contents of two
    profile files into a new profile file (useful to cumulate
    profiles data).


Changes from 1.1.4 to 1.1.5:

* add an install target for Makefile (Petter Reinholdtsen)
* add new DEBUG flags for tracking bugs :o)
* separate some code from 'fnccheck.c' and 'fncdump.c'. Now
    'fncdump.c' dont need anymore to be linked with 'fnccheck.o'.
* use 'libbfd' to extract functions name, file and line. This
    is the default behavior. You can still use 'nm' (-nm) or
    'addr2line' (-addr2line). If you dont have 'libbfd' and
    'libiberty' (from GNU binutils) use 'make fncdump_nobfd'
    instead of 'make fncdump'. It will generates 'fncdump'
    with only 'nm' and 'addr2line' approaches.
* add '-fullname' option. Make files name (if requested) to be
    displayed with full path.
* correct a bug that make 'main' exited twice for the lib when
    leaving the profiled program using 'exit' (it was changing
    the final time for main).
* developing a new approach for local time propagation from
    child functions. It compute real local times instead of
    transmiting time spend in child functions. It changes
    nothing for ordinary functions but gives correct local
    times for recursive (and cross-recursive) functions.
* add '-real-maxtime' option. Total execution time (using to
    compute time perecentages) is computed from displayed list
    of functions instead of the complete list of functions.
* few changes in flat profile display.
* starting to create a .info file in 'doc/' directory. Not
    finished yet. In fact I'm using the 'gprof' info file as
    a base, but I did something wrong and the .info generated is
    not correct. Still being updating (will be ready for V1.2).

Changes from 1.1.3 to 1.1.4:

* removing functions that compute average time per call for
    the lib in fncdump.c and fnccheck.c. Creating instead a
    fncaverage.c to perform this. Adding also targets for
    the Makefiles. This new approach uses REAL calls to the
    lib (and so generates a fnccheck.out file).
* change the -avg option in fncdump in order to call the
    fncaverage prog instead.
* internal: add a hash-table for the 'hx_search_function()'.
* change some functions to 'inline' for improvement purpose.
* switch to '-O3' optimisation (allows 'inline').
* change 'dump' into 'fncdump' (more specific).
* rename fncdump options '-calls+' and '-func+' into resp.
    '-call-details' and '-func-details'.
* change options reading system for 'fncdump' in order to accept
    several option names for the same option (in particular
    to let people use old options name (-calls+...) with the
    new version).
* update --help, --details. Add version number to --help.
* add print of full version number (including devel sub-part) when
starting the lib.
* add a shell variable FNCCHK_STOP which desactivate the lib
    at execution (I use it to compare execution time with and
    without the lib activated).
* trying to put some functions 'inline' in order to accelarate
    treatments.
* correcting an index display bug for 'called by' list.
* adding some '\n' missing during display.

Changes from 1.1.2 to 1.1.3:

* internal: create a real call-tree for functions
* -only and -not options
* -[r]propagate: allow to propagate -only/-not using the call-tree
* new archive organisation:
  - a src/ dir containing dump and lib sources
  - a test/ dir containing a test program
  - lib/ and bin/ dirs
  - recursive Makefile at root for lib, dump, test.
* moving "display" part of fnccheck.c in dump.c
* change %g to %f for time display for lisibility
* add 'static' for fnccheck functions to prevent names colisions
* change 'long long int' to 'long int' for speedup/memory optimisation
    (and because long int is enough for years...)

Changes from 1.1.1 to 1.1.2:

* improve parts of the _bad_ english of the README.txt
* add some help texts in the error messages
* add new options to 'dump' (see dump)
* change symbol extraction in order to use 'addr2line'
* new dump feature: display file/line for functions (if requested)
     -> not available with '-nm' option.
* correct bad names for C++ functions
* display MIN and MAX time for functions (see '-no-minmax')
* '--details' gives explanations on output informations.
* makefile improvements. default target display possible choice.
  target 'lib' added, target 'all' added.
  switch -g added. requiered for FILE:LINE infos.



IX.  ToDo list
--------------

* improve the hash-table in 'fncheck.c'.
* improve cycle display. At this time I just display the begin and
    the end of the cycle. Need to display all members of the cycle.
* create a 'configure'. In fact, as my lib requieres very few things,
    it is not critical.
* add better dependences for the Makefile.
* improve english of 'README.txt' and 'fncdump.texi'


X.   The 'fncaverage' program
-----------------------------

The 'fncaverage' replace the '-avg' option of 'fncdump' program.
It is now a separate executable which perform this job.
The prog can accept an option which is the number of iteration
to perform (the bigger it is, the more precise the results are, but
the more time it takes).
In fact, this program executes various kind of functions and
compare the execution time with and without the fnccheck lib activated.
Note: as a side effect, executing this program generates a
'fnccheck.out' stat file corresponding to the test functions (but
their are no valid symbols inside).
