[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2 Simple Ways to Analyze Programs with cflow.

Let’s begin our acquaintance with the GNU cflow utility with an example. Suppose you have a simple implementation of whoami command and you wish to obtain a graph of function dependencies. Here is the program:

/* whoami.c - a simple implementation of whoami utility */
#include <pwd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

int
who_am_i (void)
{
  struct passwd *pw;
  char *user = NULL;

  pw = getpwuid (geteuid ());
  if (pw)
    user = pw->pw_name;
  else if ((user = getenv ("USER")) == NULL)
    {
      fprintf (stderr, "I don't know!\n");
      return 1;
    }
  printf ("%s\n", user);
  return 0;
}

int
main (int argc, char **argv)
{
  if (argc > 1)
    {
      fprintf (stderr, "usage: whoami\n");
      return 1;
    }
  return who_am_i ();
}

Running cflow produces the following output:

$ cflow whoami.c
main() <int main (int argc,char **argv) at whoami.c:26>:
    fprintf()
    who_am_i() <int who_am_i (void) at whoami.c:8>:
        getpwuid()
        geteuid()
        getenv()
        fprintf()
        printf()

This is a direct call graph showing caller—callee dependencies in the input file. Each line starts with a function name, followed by a pair of parentheses to indicate that it is a function. If this function is defined in one of the input files, the line continues by displaying, within a pair of angle brackets, a function signature and the location of its definition. If the function calls another functions, the line ends with a colon. For example, the line

main() <int main (int argc,char **argv) at whoami.c:25>:

shows that function main is defined in file ‘whoami.c’ at line 25, as int main (int argc, char **argv). Terminating colon indicates that main invokes other functions.

The lines following this one show which functions are called by main. Each such line is indented by a fixed amount of white space (by default, four spaces) for each nesting level.

Usually cflow prints a full function signature. However, sometimes you may wish to omit some part of it. Several options are provided for this purpose. To print signatures without function names, use ‘--omit-symbol-names’ option. To omit argument list, use ‘--omit-arguments’. These options can be needed for a variety of reasons, one of them being to make the resulting graph more compact. To illustrate their effect, here is how would the first line of the above graph look if you had used both ‘--omit-’ options:

main() <int () at whoami.c:25>:

By default, cflow starts outputting direct graph from the function called main. It is convenient when analyzing a set of input files comprising an entire C program. However, there are circumstances where a user would want to see only a part of the graph starting on particular function. One can instruct cflow to start output from the desiredfunction using ‘--main’ (‘-m’) command line option. Thus, running

cflow --main who_am_i whoami.c

on the above file will produce following graph:

who_am_i() <int who_am_i (void) at whoami.c:8>:
    getpwuid()
    geteuid()
    getenv()
    fprintf()
    printf()

Many programs (such as libraries or interpreters) define functions that are not directly reachable from the main function. To produce flow graph for all functions in the program, use the ‘--all’ (‘-A’) option. The output will then include separate flow graphs for each top-level function defined in the program. These graphs will be placed after the graph for main (if it exists), and will be ordered lexicographically by the function name.

When ‘--all’ is used twice, graphs for all global functions (whether top-level or not) will be displayed.

To disable special handling of the main function, use the ‘--no-main’ option.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated on March 24, 2021 using texi2html 5.0.