Programming Utilities Guide

Running prex

After you have prex connected to your program, use prex commands to change the parameters of the data to be collected. You can use the prex list command to see all the probes in your program. As your program runs, each time a probe point is executed, information is recorded in the trace file. You look at the collected information with tnfdump(), described in "Reading the tnfdump File".

You can attach and detach prex from your program repeatedly, creating multiple sessions. For example, in your first session you could start the target with prex, set up the probes, and type quit resume.

This will start prex, define the information you want to collect, quit prex, and start collecting information by resuming execution of your program. The commands to do this are shown in Table 1-2.

In a following session, you could attach prex to the same program, reconfigure the probes, and again type continue. You can do this any number of times.


Note -

All traces are written to the trace file name specified in the first session --this file name cannot be changed.


Table 1-2 Basic prex Commands

Command 

Result 

% prex a.out

Attach prex to your program and start prex.

prex> enable $all

Enable all the probes. 

prex> quit resume

Quit prex and resume execution of program.

Components of the prex Command

The programmer who has inserted the probe points in the source code has assigned various attributes and (optional) values to each probe point. For example, each probe point has a "name" attribute whose value is the name the programmer chose for it.

Look at Table 1-3 for a list of the predefined attributes and the meanings of their values. The prex command lets you select a group of probe points by matching on their attributes or values. You can then trace or debug the selected probe points.

Table 1-5 lists the prex commands and their actions.

In code Example 1-1, the TNF_PROBE macro defines the probe point named work_start. This probe point has two arguments whose values will be logged--state and message. Each time the probe named work_start is encountered, a time stamp and the values of the variables state and message are logged to the trace file.


Example 1-1 prex Attributes and Values

	#include <tnf/probe.h>
	
	int
	work(int state, char *message)
	{
    TNF_PROBE_2(work_start, "work_module work"
               "sunw%debug in function work",
               tnf_long, int_input, state,
               tnf_string, string_input, message);
   ...
   ...
	}

For more information on TNF_PROBE macros, including this example, see "Using the TNF_PROBE Macros".

Table 1-3 lists the predefined attributes.

Attributes

Attributes are characteristics by which you identify probe points in your code. Table 1-3 lists the predefined attributes. You can add more attributes with the TNF_PROBE macros. See "Using the TNF_PROBE Macros".

Table 1-3 Predefined Attributes

Attribute 

Characteristics 

Value  

enable

A probe point performs the action that it is set up for only if it is enabled. For example, even when the tracing state is set, tracing occurs only if the probe point has been enabled. 

OFF (default) 

file

The name of the file containing the probe point. 

work.c
funcs

Shows the list of probe functions connected to this probe. Currently, only the debug function is available. 

<no value> (default) 

keys

The groups to which the probe point belongs. If any key in a probe point is enabled, then that probe point is enabled.  

work_module 

work 

line

The line number in the code on which the probe point occurs. 

10 

name

The name of the probe point. 

work_start 

object

The name of the shared object or executable that the probe is in. Useful for selecting all the probes in a particular module. 

work 

slots

The names of the probe point arguments (arg_name_n), see page 41. 

int_input 

string_input 

trace

When tracing for a probe point is on, a line is written to the trace file each time the probe point is executed in your program. 

ON (default) 

Grammar for Matching Probes

Select probes based on their attributes and values. The selection specification is called a selector_list. Each attribute or value can be described as one of the following:

A selector_list consists of one or more selector= selector items. If the initial selector= is not provided, it defaults to keys=. For example, the enable command is specified as :

enable selector_list

An example of this command is:

enable name=/first/ file='sampleZ.c'

This enables all probe points with either the name attribute containing the value first (a regular expression match), or the file attribute equal to the value sampleZ.c (Note that the trace is a disjunction and not a conjunction.)

Use $set_name as a shorthand alias for a selector_list specification. In the following example, the set_name is myprobes.

create $myprobes name=/first/ file='sampleZ.c'
enable $myprobes

This does the same thing as the previous example. The set_name follows the identifier naming rules. The $all default set selects all probes in the program.

Reserved Words

Table 1-4 lists the reserved words. Enclose them in single quotes if you use them to select attributes or values.

Table 1-4 Reserved Words
addallocbuffer
clearconnectcontinue
createdeallocdelete
disableenablefcns
filterhelphistory
killktracelist
offonpfilter
probesquitresume
setssourcesuspend
traceuntracevalues

For example:

enable 'trace'='on'

means enable all probes whose trace attribute has the value of ON. Both trace and on are reserved words, so they both have to be enclosed in single quotation marks.

Table 1-5 prex Commands

Command 

Action 

clear $set_name

clear selector_list

Disconnect connected probe functions. 

 

connect &debug $set_name

connect &debug selector_list

Connect the debug function to the probe points. This does not enable the probe points. The debug function sends its output to stderr and not to the trace file.

 

continue

Resume execution of your program, leaving prex attached.

create $set_name selector_list

Create a set with probe points matching selector_list. Also creates an alias, $set_name, for the selector_list.

enable $set_name

enable selector_list

disable $set_name

disable selector_list

Control whether the probe points perform the action they are set up for. Probe points are disabled by default; prex does not turn on tracing. The cheapest way (in terms of execution time at the probe point) to stop a probe point from tracing is to use the disable command.

The enable and disable commands are a master switch. If a probe point is not enabled, even if the probe point is connected to the debug() function and trace is on, no information is sent to stderr or to the trace file.

 
 
 

help

List all available prex commands.

list attributes probes selector_list

list attributes probes $set_name

List whether specified probe points are enabled or disabled, whether they have tracing on or off, and what the connected probe function is. Attributes are selectors as described in "Attributes ". For example,

list name file probes $all

lists only name and file values for matching probe points, while the command

list probes $all

lists all default attributes and their values (name, enable, trace, file, line, and funcs).

 

list fcns

List the defined functions (currently, only &debug is defined).

list history

List the control command history. The history of the commands used with connect, clear, trace, untrace, enable, and disable are executed whenever a new shared object is brought into your program through dlopen(). See "dlopen() and dlclose() and History".

list sets

List the defined sets. 

list values attributes

List the unique values associated with the specified attributes. For example, list values keys lists all the unique keys in the program.

source filename

Source a file of prex commands. filename is a quoted string.

trace $set_name

>trace selector_list

untrace $set_name

untrace selector_list

Control the tracing action of the probe points. trace and untrace determine whether a probe point generates a trace record when it is executed. Neither trace nor untrace enables the probe points.

 

The default mode is that tracing is on. 

 

The untrace command is useful when you are interested in getting only debug output. If you are using this, your probe should be enabled with tracing off and debug on.

 

Tracing disturbs your program less than the debug function does because trace writes to an mmap'd file while debug writes to stderr.

 
 
 

quit

Quit prex; if your program was loaded with prex, it will be killed; if your program was attached to prex, it will be resumed.

quit kill

Quit prex and kill your program.

quit resume

Quit prex and resume execution of your program.

quit suspend

Quit prex and leave your program suspended.

Tracing, Enabling, and Connecting

To trace at a probe point, the probe point must have trace on and it must be enabled. To debug at a probe point, the probe point must be connected to the debug function and must be enabled.

Table 1-6 shows which combinations of tracing, enabling, and connecting result in which actions.

Table 1-6 Tracing, Enabling, and Connecting Actions

Enabled or Disabled 

Tracing State (On/Off) 

Debug State (Connected/Cleared) 

Results In 

Enabled 

On 

Connected 

Tracing and Debugging 

Enabled 

On 

Cleared 

Tracing only 

Enabled 

Off 

Connected 

Debugging only 

Enabled 

Off 

Cleared 

Nothing 

Disabled 

On 

Connected 

Nothing 

Disabled 

On 

Cleared 

Nothing 

Disabled 

Off 

Connected 

Nothing 

Disabled 

Off 

Cleared 

Nothing 

Controlling prex From a Script

Enter commands to prex either from the prex command line or from a file containing prex commands.

When you start prex, it searches for a file named .prexrc first in $HOME/ and next in the directory from which you started prex. Commands are read from all files that are found. Therefore it is possible to have a .prexrc file in the current directory that overrides defaults that are set up by the .prexrc file in the home directory.

After reading any .prexrc files that are found, input is expected from the prex command line. To set up an experiment entirely using .prexrc files, the last statement in it can be quit resume, which quits prex but lets your program resume.

Also, when prex is running you can use the source filename command to specify a file from which prex reads commands. This file can have any name you like.

As with commands entered from the prex command line, all commands in the script should be in ASCII. The following rules apply:

A Sample C Program

This program, cookie.c, asks for a cookie. The response must be entered in uppercase, or it is incorrect. You can also find the prime factor of a number. In the process of doing these two things, you can see how the trace function works.

To compile this program and get an executable called cookie(), use

$ cc -o cookie cookie.c 

Five probe points are defined (and highlighted) in this program. They are named start (line 17), inloop (line 33), factor_start (line 60), found_a_factor (line 65), and factor_end (line 72). More information about these probe points is gathered and explained in "A Sample prex Session".


Example 1-2 Code for cookie.c()

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <tnf/probe.h>

#define MAX_RESPONSE_SIZE	256

static void find_factor(int n);

int
main(int argc, char **argv)
{
    boolean_t	shouldexit = B_FALSE;
    int 	sum = 0, max_loop = 5;
    int		i;

    TNF_PROBE_0(start, "cookie main", 
         "sunw%debug starting main");

    while (!shouldexit) {
	      char	response[MAX_RESPONSE_SIZE];
	      int	factor_input;

      	(void) printf("give me a COOKIE! ");
	      (void) scanf("%s", response);

      	if (!strcmp(response, "COOKIE")) {
	           (void) printf("thanks!\n");
	           shouldexit = B_TRUE;
      	}

      	else if (!strcmp(response, "loop")) {
       	    for (i = 0; i < max_loop; i++) {
	             	TNF_PROBE_2(inloop, "cookie main
                           loop","sunw%debug in the loop",
			                       	tnf_long, loop_count, 	i,
		                       		tnf_long, total_iterations, 	sum);
             		sum++;
           	}
	         		max_loop += 2 ;
     		}

	    	else if (!strcmp(response, "factor")) {
         			(void) printf("number you want factored? ");
	         		(void) scanf("%d", &factor_input);
	         		find_factor(factor_input);
    		}

	    	else {
	         		(void) printf("not a %s, ", response);
		    }
    }
    return 0;

}   /* end main */
static void
find_factor(int n)
{
    int i;

    (void) printf("\tfactors of %d = ", n);
    TNF_PROBE_1(factor_start, "factor", "",
      		tnf_long, input_number, n);

    for (i=2; i <= n; i++) {
      		while (n % i == 0) {
		        	TNF_PROBE_2(found_a_factor, "cookie find_factor",
               "", tnf_long, searching_for, n,
	           			tnf_long, factor, i);
	        		(void) printf("%d ", i);
	        		n /= i;
      		}
    }
    TNF_PROBE_0(factor_end, "factor", "");
    (void) printf("\n");
}

A Sample prex Session

This sample of a prex session is designed to show the different capabilities of prex. The data collected when cookie is run is shown in "Reading the tnfdump File".

% prex cookie     /* prex is loading the executable cookie. */
Target process stopped
Type "continue" to resume the target, "help" for help ...
prex> list sets
$all      'keys'=/.*/    /* One set is defined--$all 
                            (which is all the probes). */
prex> list fcns
&debug    tnf_probe_debug      /* The debug function is 
                                  the only one available. */
prex> list probes $all
name=inloop enable=off trace=on file=cookie.c line=35 funcs=<no value>
name=factor_end enable=off trace=on file=cookie.c line=72 funcs=<no value>
name=factor_start enable=off trace=on file=cookie.c line=61 funcs=<no value>
name=found_a_factor enable=off trace=on file=cookie.c line=67 funcs=<no value>
name=start enable=off trace=on file=cookie.c line=17 funcs=<no value>
prex>/*  The line number shows the end of each of the five probes. */
prex> create $factor /factor/    /* Create a new set that
                            matches any probe whose "keys" */
prex>       /* attribute contains the string "factor". */
prex> list sets
$all      'keys'=/.*/
$factor   'keys'=/factor/        
/* A new set named "factor" 
                                   is created and now shows
                                   up in */
prex>                              
  /* the list of sets. */
prex> list probes $factor            
/* This line tells you which probes matched the set
$factor.*/
name=factor_end enable=off trace=on file=cookie.c line=72 funcs=<no value>
name=factor_start enable=off trace=on file=cookie.c line=61 funcs=<no value>
name=found_a_factor enable=off trace=on file=cookie.c line=67 funcs=<no value>
prex> list probes $all          /* Check to see if any 
                                 probes are enabled. */
name=inloop enable=off trace=on file=cookie.c line=35 funcs=<no value>
name=factor_end enable=off trace=on file=cookie.c line=72 funcs=<no value>
name=factor_start enable=off trace=on file=cookie.c line=61 funcs=<no value>
name=found_a_factor enable=off trace=on file=cookie.c line=67 funcs=<no value>
name=start enable=off trace=on file=cookie.c line=17 funcs=<no value>
prex>                  /* None are enabled, 
                      but all have trace on. */

prex> enable $all             /* Enable all the probes.*/
prex> list probes $all        /* Check again to see if any 
                              probes are enabled. */  
name=inloop enable=on trace=on file=cookie.c line=35 funcs=<no value>
name=factor_end enable=on trace=on file=cookie.c line=72 funcs=<no value>
name=factor_start enable=on trace=on file=cookie.c line=61 funcs=<no value>
name=found_a_factor enable=on trace=on file=cookie.c line=67 funcs=<no value>
name=start enable=on trace=on file=cookie.c line=17 funcs=<no value
prex> list values name              /* Find out what the probe names are. */
name =                              
	   factor_end                   
	   factor_start
	   found_a_factor
	   inloop
	   start
prex> list values /.*/          /* List all predefined
                              attributes with their values. */
enable =              /* Only unique attributes are listed.*/
    on 
file =
	   cookie.c
funcs =
	  
keys =
	   cookie
	   factor
	   find_factor
	   loop
	   main
line =
	   17
	   35
	   61
	   67
	   72
name =
	   factor_end
	   factor_start
	   found_a_factor
	   inloop
	   start
object =
	   cookie
slots =
	   factor
	   input_number
	   loop_count
	   searching_for
	   total_iterations
sunw%debug =           /* The user-defined macro, sunw%debug, 
                       is also listed. */
	   in     /* This macro is defined in line 17 of cookie.c. */
	   loop
	   main
	   starting
	   the
trace =
	   on
prex> list values object
object =
	   cookie
prex> connect &debug name=inloop
prex> list /.*/ probes $all         /* List all the
                           information about all the probes */
enable=on trace=on object=cookie funcs=<no value> name=inloop slots=loop_count
total_iterations keys=cookie main loop file=cookie.c line=35 sunw%debug=in the loop 
enable=on trace=on object=cookie funcs=<no value> name=factor_end slots=<no value>
keys=factor file=cookie.c line=72
enable=on trace=on object=cookie funcs=<no value> name=factor_start slots=input_number
keys=factor file=cookie.c line=61 
enable=on trace=on object=cookie funcs=<no value> name=found_a_factor slots=searching_for
factor keys=cookie find_factor file=cookie.c line=67 
enable=on trace=on object=cookie funcs=<no value> name=start slots=<no value> keys=cookie
main file=cookie.c line=17 sunw%debug=starting main 
prex> continue
give me a COOKIE! loop       
 /* An example of loop counts*/
probe inloop; sunw%debug "in the loop"; loop_count=0; total_iterations=0;
probe inloop; sunw%debug "in the loop"; loop_count=1; total_iterations=1;
probe inloop; sunw%debug "in the loop"; loop_count=2; total_iterations=2;
probe inloop; sunw%debug "in the loop"; loop_count=3; total_iterations=3;
probe inloop; sunw%debug "in the loop"; loop_count=4; total_iterations=4;
give me a COOKIE! factor	
number you want factored? 25
	factors of 25 = 5 5
give me a COOKIE! factor
number you want factored? 43645729
	factors of 43645729 = 43645729
give me a COOKIE! ^C Target process stopped
Type "continue" to resume the target, "help" for help...
prex> continue
give me a COOKIE! biscuit
not a biscuit, give me a COOKIE!  cookie
not a cookie, give me a COOKIE! COOKIE
thanks!
prex: target process finished