This chapter discusses how to debug programs in Prism. It also describes how to use events to control the execution of a program. The principles that apply to debugging serial programs also apply to debugging message-passing programs. However, debugging a message-passing program can be considerably more complex than debugging a serial program, since you are in effect debugging multiple individual programs concurrently. MP Prism's concept of psets lets you focus your debugging efforts on the processes that are of particular interest. The following discussions distinguish features (where necessary) that apply exclusively to debugging the processes of message-passing programs:
A typical approach to debugging is to stop the execution of a program at different points so that you can perform various actions--for example, check the values of variables. You stop execution by setting a breakpoint. If you perform a trace, execution stops, then automatically continues.
Breakpoints and traces are events. You can specify before the execution of a program begins what events are to take place during execution. When an event occurs:
The execution pointer moves to the current execution point.
A message is printed in the command window.
If you specified that an action was to accompany the event (for example, the printing of a variable's value), it is performed.
If the event is a trace, execution then continues. If it is a breakpoint, execution does not resume until you explicitly order it to (for example, by choosing Continue from the Execute menu).
Prism provides various ways of creating these events--for example, by issuing commands, or by using the mouse in the source window. " Setting Breakpoints" describes how to create breakpoint events; " Tracing Program Execution" describes how to create trace events. " Using the Event Table" describes the Event Table, which provides a unified method for listing, creating, editing, and deleting events.
See " Events Taking Pset Qualifiers (MP Prism Only)" for a discussion of events in MP Prism.
You can define events so that they occur:
When the program reaches a certain point in its execution - For example, at a specified line or function.
When the value of a variable changes - For example, you can define an event that tells Prism to stop the program when x changes value. This kind of event is sometimes referred to as a watchpoint. It slows execution considerably, since Prism has to check the value of the variable after each statement is executed.
At every line or assembly-language instruction.
Whenever a program is stopped - For example, you can define an event that tells Prism to print the value of x whenever the program stops.
Such events are referred to as triggering conditions.
In addition, you can qualify an event as follows:
So that it occurs only if a specified condition is met - For example, you can tell Prism to stop at line 25 if x is not equal to 1. Like watchpoints, this kind of event slows execution.
So that it occurs only after its triggering condition has been met a specified number of times - For example, you can tell Prism to stop the tenth time that the program reaches the function foo.
You can include one or more Prism commands as actions that are to take place as part of the event. For example, using Prism commands, you can define an event that tells Prism to stop at line 25, print the value of x, and do a stack trace.
The Event Table provides a unified method for controlling the execution of a program. Creating an event in any of the ways discussed later in this chapter adds an event to the list in this table. You can also display the Event Table and use it to:
Add new events
Delete existing events
Edit existing events
You display the Event Table by choosing the Event Table selection from the Events menu.
This section describes the general process of using the Event Table.
Figure 4-1 shows the Event Table.
The top area of the Event Table is the event list--a scrollable region in which events are listed. When you execute the program, Prism uses the events in this list to control execution. Each event is listed in a format in which you could type it as a command in the command window. It is prefaced by an ID number assigned by Prism. For example, in Figure 4-1, the events have been assigned the IDs 1 and 2.
The middle area of the Event Table is a series of fields that you fill in when editing or adding an event; only a subset of the fields is relevant to any one event. The fields are:
ID - This is an identification number associated with the event. You cannot edit this field.
Location - Use this field to specify the location in the program at which the event is to take place. Use the syntax "filename":line-number to identify the source file and the line within this file. If you just specify the line number, Prism uses the current file. There are also three keywords you can use in this field:
Use eachline to specify that the event is to take place at each line of the program; this is the default.
Watch - Use this field to specify a variable or expression whose value(s) are to be watched; the event takes place if the value of the variable or expression changes. (If the variable is an array or a parallel variable, the event takes place if the value of any element changes.) This slows execution considerably.
Actions - Use this field to specify the action(s) associated with the event. The actions can be most Prism commands; separate multiple commands with semicolons. (The commands that you can't include in the Actions field are attach, core, detach, load, return, run, and step.)
Condition - Use this field to specify a logical condition that must be met if the event is to take place. The logical condition can be any language expression that evaluates to true or false. See " Writing Expressions in Prism" for more information about writing expressions in Prism. Specifying a condition slows execution considerably, unless you also specify a location at which the condition is to be checked.
After - Use this field to specify how many times a triggering condition is to be met (for example, how often a program location is reached) before the event is to take place. The Event Table updates during execution to show the current count (that is, how many times are left for the triggering condition to be met before the event is to take place). Once the event takes place, the count is reset to the original value. The default setting is 1, and the event takes place each time the condition is met. See " Overview of Events" for a discussion of triggering conditions.
Stop - Use this field to specify whether or not the event is to halt execution of the program. Putting a y in this field creates a breakpoint event; putting an n in this field creates a trace event.
Inst - Use this field to specify whether to display a disassembled assembly-language instruction when the event occurs.
Silent - Use this field to specify whether or not the event is to cause a message to appear in the command window when it occurs.
Enabled - Use this field to specify whether the event is enabled. Putting an n in this field disables the event; it still exists, but it does not affect program execution.
The buttons beneath these fields are for use in creating and deleting events, and are described below.
The area headed Common Events contains buttons that provide shortcuts for creating certain standard events.
Click on Close or press the Esc key to cancel the Event Table window.
You can either add an event, editing field by field, or you can use the Common Events buttons to fill in some of the fields for you. You would add an event from the beginning if it weren't similar to any of the categories covered by the Common Events buttons.
To add an event, editing field by field:
Click on the New button.
All values currently in the fields are cleared.
Fill in the relevant fields to create the event.
Click on the Save button to save the new event.
It appears in the event list.
To use the Common Events buttons to add an event:
Click on the button for the event you want to add--for example, Print.
This fills in certain fields (for example, it puts print on dedicated in the Actions field) and highlights the field or fields that you need to fill in (for example, it highlights the Location field when you click on Print, because you have to specify a program location).
Fill in the highlighted field(s). You can also edit other fields, if you like.
Click on Save to add the event to the event list.
Most of these Common Events buttons are also available as separate selections in the Events menu. This lets you add one of these events without having to display the entire Event Table. The menu selections, however, prompt you only for the field(s) you must fill in. You cannot edit other fields.
Individual Common Events buttons are discussed throughout the remainder of this guide.
You can also create a new event by editing an existing event; see " Editing an Existing Event".
You can delete events using the Event Table or the Delete selection from the Events menu.
To delete an existing event, using the Event Table:
Click on the line representing the event in the event list, or move to it with the up and down arrow keys.
This causes the components of the event to be displayed in the appropriate fields beneath the list.
Click on the Delete button.
You can also choose the Delete selection from the Events menu to display the Event Table. You can then follow the procedure described above.
Deleting a breakpoint at a program location also deletes the B in the line-number region at that location.
You can edit an existing event to change it, or to create a new event similar to it.
To edit an existing event:
Click on the line representing the event in the event list, or move to it with the up and down arrow keys.
This causes the components of the event to be displayed in the appropriate fields beneath the list.
Edit these fields.
For example, you can change the Location field to specify a different location in the program.
Click on Replace to save the newly edited event in place of the original version of the event.
Click on the Save button to save the new event in addition to the original version of the event; it is given a new ID and is added to the end of the event list. Clicking on Save is a quick way of creating a new event similar to an event you have already created.
You can disable and enable events. When you disable an event, Prism keeps it in the event list, but it no longer affects execution. You can subsequently enable it when you once again want it to affect execution. This can be more convenient than deleting events and then redefining them.
From the Event Table - The Event Table has an Enabled field. By default, there is a y in this field, meaning that the event being defined or edited is enabled. Click on the field and change the y to an n to disable the event. The event remains in the event list, but is labeled (disabled). You can then edit the event as described in " Editing an Existing Event" and change the field back to a y to enable the event once again.
From the command line - Issue the disable command to disable an event. Use the event's ID as the argument. You can obtain this ID from the event list in the Event Table, or by issuing the show events command.
For example, this sequence of commands displays the event list, then disables an event, then re-displays the event list:
(prism) show events(1) trace
(2) when stopped { print board }
(prism) disable 1
event 1 disabled
(prism) show events
(1) trace (disabled)
(2) when stopped { print board }
Issue the enable command to enable an event that has been disabled. Specify the ID of the disabled event as the argument.
Events that you create for a program are automatically maintained when you reload the same program during a Prism session. This saves you the effort of redefining these events each time you reload a program.
Note these points:
Prism prints a warning message if it can't maintain an event--for example, because the event is supposed to occur at a source line that no longer exists. Obviously, changing the program can also change the meaning of events; a breakpoint set at line 32, for example, may still be a valid event, but it may not be the event you want if you have deleted lines earlier in the program.
Disabled events become enabled when a program is reloaded.
Events are deleted when you leave Prism.
To use Prism commands to save your events to a file, and then execute them from the file rather than individually:
Issue the show events command, which displays the event list.
Redirect the output to a file. For example,
show events @ primes.events
(See " Redirecting Output" for information on redirecting output.)
Edit this file to remove the ID number at the beginning of each event.
This leaves you with a list of Prism commands.
Issue the source command when you want to read in and execute the commands from the file.
For example,
source primes.events
Events in MP Prism can take a pset qualifier. You can specify this in an event field in MP Prism's Event Table, as shown in Figure 4-2.
If you don't supply a pset qualifier, the event applies to the current pset. If you create the event before changing the current set, the event applies to the default set, which is all.
Thus,
stop in receive pset notx
sets a breakpoint in the receive routine for the processes in the set notx. Each process in the set stops when it reaches this routine. It is possible, of course, that some processes may never reach this routine. This becomes an issue when you include actions in an event; see below.
If all the processes in the pset have stopped, you can continue them by issuing a command like
cont pset notx
Here is another example:
stop if x > 10
This command stops execution for any process in the current pset if the process's value for the variable x is greater than 10.
Prism evaluates the expression in the condition locally--that is, separately for each process. Similarly, if a and b are arrays,
stop if sum(a) > sum(b)
stops execution for a process in the current set if the sum of the values of a in that process is greater than the sum of the values of b.
All processes that are stopped at breakpoints are members of the predefined pset break.
If you use a dynamic pset as a qualifier for an event, its membership is evaluated when you issue the command defining the event. Thus, the command
stop at 10 pset interrupted
creates a breakpoint only in the processes that are interrupted at the time the command is issued. If no processes are currently interrupted, you receive an error message.
One result of this is that you cannot define events that involve dynamic psets before the program starts execution.
If you use a user-defined variable pset as a qualifier, its membership is determined by the most recent eval pset command you issued for that pset.
As is the case with dynamic psets, you cannot define events that involve variable psets before the program starts execution.
Events in both MP Prism and scalar Prism can take action clauses. For example, in MP Prism the following action clause prints x for the pset foo when the members of foo are stopped at line 10:
stop at 10 {print x} pset foo
Associating an action with an event forces a global synchronization at the breakpoint or tracepoint. In the example above, every process in pset foo must stop at line 10 before x can be printed. If a member does not stop at line 10, the action never takes place. In a trace event, all processes in the pset must stop at the specified place and synchronize; the action then takes place, and the processes automatically continue execution.
You can include an eval pset command as an event action. For example,
stop in send {eval pset sending}
evaluates the pset sending when all the members of the current pset are stopped in send. You receive error messages if it is impossible to evaluate membership in a pset (for example, because a variable in the set definition is not active).
Note these limitations in using event actions: i:
I n MP Prism, you cannot include a pset qualifier in the action. The command in the action clause takes its pset from the pset of the event.
In both MP Prism and scalar Prism, you cannot include commands that affect program execution, specifically:
In both MP Prism and scalar Prism, you cannot include the load, reload, return, and core commands.
Issue the show events command with a process number as an argument to display all events associated with that process. For example,
(prism) show events (1) trace (2) when stopped { print board } (prism) disable 1 event 1 disabled (prism) show events (1) trace (disabled) (2) when stopped { print board }
Issuing show events with no arguments has its standard behavior; that is, it prints out all events.
If you create an event that applies to a particular pset, and subsequently delete the pset, the event continues to exist. Its printed representation, however, is changed so that it shows the processes that were members of the pset at the time you deleted the set.
A breakpoint stops execution of a program when a specific location is reached, if a variable or expression changes its value, or if a certain condition is met. Breakpoints are events that Prism uses to control execution of a program. This section describes the methods available in Prism for setting a breakpoint.
You can set a breakpoint
By using the line-number region
By using the Event Table and the Events menu
From the command window, by issuing the command stop or when
You'll probably find it most convenient to use the line-number region for setting simple breakpoints; however, the other two methods give you greater flexibility--for example, in setting up a condition under which the breakpoint is to take place.
In all cases, an event is added to the list in the Event Table. If you delete the breakpoint using any of the methods described in this section, the corresponding event is deleted from the event list. If you set a breakpoint at a program location, a B appears next to the line number in the line-number region.
To use the line-number region to set a breakpoint, the line at which you want to stop execution must appear in the source window. If it doesn't, you can scroll through the source window (if the line is in the current file), or use the File or Func selection from the File menu to display the source file you are interested in.
To set a breakpoint in the line-number region:
Position the mouse pointer to the right of the line numbers; the pointer turns into a B.
Move the pointer next to the line at which you want to stop execution.
Left-click the mouse.
A B is displayed, indicating that a breakpoint has been set for that line.
A message appears in the command window confirming the breakpoint, and an event is added to the event list.
The source line you choose must contain executable code; if it does not, you receive a warning in the command window, and no B appears where you clicked.
Shift-click on the letter in the line-number region to display the complete event (or events) associated with it.
See " Using the Line-Number Region" for more information on the line-number region.
See " Using the Line-Number Region in MP Prism" for a discussion of the line-number region in MP Prism.
To delete the breakpoint, left-click on the B that represents the breakpoint you want to delete. The B disappears; a message appears in the command window, confirming the deletion.
As described in " Moving Through the Source Code", you can split the source window to display source code and the corresponding assembly code.
You can set a breakpoint in either pane of the split source window. The B appears in the line-number region of both panes, unless you set the breakpoint at an assembly code line for which there is no corresponding source line.
Deleting a breakpoint from one pane of the split source window deletes it from the other pane as well.
MP Prism provides variations on the way that the line-number region displays breakpoints and tracepoints. In MP Prism:
It displays a B next to a line number if all processes in the current pset have a breakpoint set at that line.
It displays a b if some but not all of the processes in the current pset have a breakpoint set at that line.
It displays a T if all processes in the current pset have a tracepoint set at that line.
It displays a t if some but not all of the processes in the current pset have a tracepoint set at that line.
If there is a mixture of breakpoints and tracepoints set on the line, Prism uses the B-b-T-t sequence to determine what letter to display. For example, if a line has a breakpoint set in one process and a tracepoint set in all processes, Prism displays a b.
As in scalar Prism, you can shift-click on the letter in the line-number region to display the complete event (or events) associated with it.
To set a breakpoint, choose the Stop <loc> or Stop <var> selection from the Events menu. These choices are also available as Common Events buttons within the Event Table itself; see " Adding an Event".
Stop <loc> prompts for a location at which to stop the program. You can also specify a function or procedure; the program stops at the first line of the function or procedure.
Stop <var> prompts for a variable name. The program stops when the variable's value changes. The variable can be an array, in which case execution stops any time any element of the array changes. This slows execution considerably.
In addition, Stop <cond> is available as a Common Events button. It prompts for a condition, which can be any expression that evaluates to true or false; see " Writing Expressions in Prism" for more information on expressions. The program stops when the condition is met. This slows execution considerably.
You can also use the Event Table to create combinations of these breakpoints; for example, you can create a breakpoint that stops at a location if a condition is met. In addition, you can use the Actions field of the Event Table to specify the Prism commands that are to be executed when execution stops.
To delete a breakpoint, choose the Delete selection from the Events menu, or use the Delete button in the Event Table itself. See " Deleting an Existing Event".
Issue the command stop (or when, which is an alias for stop) from the command line to set a breakpoint. The syntax of the stop command is also used by the stopi, trace, and tracei commands, which are discussed below. The general syntax for all the commands is:
command [variable | at line | in func] [if expr] [{cmd[; cmd...]}] [after n]
where
command - As mentioned above, can be stop, stopi, when, trace, or tracei.
variable - Is the name of a variable. The command is executed (in other words, the event takes place) if the value of the variable changes. If the variable is an array, an array section, or a parallel variable, the command is executed if the value of any element changes. This form of the command slows execution considerably. You cannot specify both a variable and a program location.
line - Specifies the line number where the stop or trace is to be executed. If the line is not in the current file, use the format:
at "filename":line-number
func - Is the name of the function or procedure in which the stop or trace is to be executed.
expr - Is any language expression that evaluates to true or false. This argument specifies the logical condition, if any, under which the stop or trace is to be executed. For example,
if a .GT. 1
This form of the command slows execution considerably, unless you combine it with the at line syntax. See " Writing Expressions in Prism" for more information on writing expressions in Prism.
cmd - Is any Prism command (except attach, core, detach, load, return, run, or step). This argument specifies the actions, if any, that are to accompany the execution of the stop or trace. For example, {print a} prints the value of a. If you include multiple commands, separate them with semicolons.
n - Is an integer that specifies how many times a triggering condition is to be reached before the stop or trace is executed; see " Overview of Events" for a discussion of triggering conditions. This is referred to as an after count. The default is 1. Once the stop or trace is executed, the count is reset to its original value. Note that if there is both a condition and an after count, the condition is checked first.
The first option listed (specifying the location or the name of the variable) must come first on the command line; the other options, if you include them, can be in any order.
For the when command, you can use the keyword stopped to specify that the actions are to occur whenever the program stops execution.
When you issue the command, an event is added to the event list. If the command sets a breakpoint at a program location, a B appears in the line-number region next to the location.
To stop execution the tenth time in function foo and print a:
stop in foo {print a} after 10
To stop at line 17 of file bar if a is equal to 0:
stop at "bar":17 if a == 0
To stop whenever a changes:
stop a
To stop the third time a equals 5:
stop if a .eq. 5 after 3
To print a and do a stack trace every time the program stops execution:
when stopped {print a; where}
To set a breakpoint at a machine instruction, issue the stopi command, using the syntax described above, and specifying a machine address. For example,
stopi at 0x1000
stops execution at address 1000 (hex).
The history region displays the address and the machine instruction. The source pointer moves to the source line being executed.
To delete a breakpoint via the command window, first issue the show events command. This prints out the event list. Each event has an ID number associated with it.
To delete one or more of these events, issue the delete command, listing the ID numbers of the events you want to delete; separate multiple IDs with one or more blank spaces. For example,
delete 1 3
deletes the events with IDs 1 and 3. Use the argument all to delete all existing events.
You can trace program execution by using the Event Table or Events menu, or by issuing commands. All methods add an event to the Event Table. If you trace a source line, Prism displays a T next to the line in the line-number region.
As described earlier, tracing is essentially the same as setting a breakpoint, except that execution continues automatically after the breakpoint is reached. When tracing source lines, Prism steps into procedures if they were compiled with the -g option; otherwise it steps over them as if it had issued a next command.
To trace program execution, choose the Trace, Trace <loc>, or Trace <var> selection from the Events menu. These choices are also available as Common Events buttons within the Event Table itself.
Trace <loc> prompts for a source line. Prism displays a message immediately prior to the execution of this source line.
Trace <var> prompts for a variable name. A message is printed when the variable's value changes. The variable can be an array, an array section, or a parallel variable, in which case a message is printed any time any element changes. This slows execution considerably.
In addition, Trace <cond> is available as a Common Events button. It prompts for a condition, which can be any expression that evaluates to true or false; see " Writing Expressions in Prism" for more information on writing expressions. The program displays a message when the condition is met. This also slows execution considerably.
For variations of these traces, you can create your own event in the Event Table. You can also use the Actions field to specify Prism commands that are to be executed along with the trace.
To delete a trace, choose the Delete selection from the Events menu, or use the Delete button in the Event Table. See " Deleting an Existing Event".
Issue the trace command from the command line to trace program execution. Issuing trace with no arguments causes each source line in the program to be displayed in the command window before it is executed.
The trace command uses the same syntax as the stop command; see " Using Commands". For example:
To trace and print a on every source line:
trace {print a}
To trace line 17 if a is greater than 10:
trace at 17 if a .GT. 10
In addition, Prism interprets
trace line-number
as being the same as
trace at line-number
To trace machine instructions, use the tracei command, specifying a machine address. When tracing machine instructions, Prism follows all procedure calls down. The tracei command has the same syntax as the stop command; see " Using Commands".
The history region displays the address and the machine instruction. The execution pointer moves to the next source line to be executed.
To delete a trace, use the show events command to obtain the ID associated with the trace, then issue the delete command with the ID as its argument. See " Using Commands".
The call stack is the list of procedures and functions currently active in a program. Prism provides you with methods for examining the contents of the call stack.
See " Where Graph" for a discussion of displaying the call stack in MP Prism.
From the menu bar - Choose the Where selection from the Debug menu. The Where window is displayed; see Figure 4-4. The window contains the call stack; it is updated automatically when execution stops or when you issue commands that change the stack.
From the command window - Issue the where command on the command line. If you include a number, it specifies how many active procedures are to be displayed; otherwise, all active procedures are displayed in the history region.
Values of arguments in displayed procedures are shown in the default radix, which is decimal unless you change it via the set $radix command; see " Changing the Default Radix".
Moving up through the call stack means heading toward the main procedure. Moving down through the call stack means heading toward the current stopping point in the program.
Moving through the call stack changes the current function and repositions the source window at this function. It also affects the scope that Prism uses for interpreting the names of variables you specify in expressions and commands.
Prism provides these methods for moving through the call stack:
From the menu bar - Choose Up or Down from the Debug menu. Up moves up one level in the call stack; Down moves down one level. These selections are available by default in the tear-off region.
From the command window - Issue the up command on the command line to move up one level. If you specify an integer as an argument, you move up that number of levels. Issue the down command to move down one level; specifying an integer moves down that number of levels.
From the Where window - If the Where window is displayed, clicking on a function in it changes the stack level to make that function current.
In MP Prism, the scope of the current process determines the scope for resolving the names of variables. See " The Current Process" for a discussion of the current process.
If a command applies to a pset other than the current set, Prism uses the scope of that set's current process.
It is possible that other members of the pset will have different scopes from that of the current process, or that its scope level will not even exist in these processes. In these cases, you receive an error message when you try to issue a command (for example, print or display) that requires a consistent scope. To solve the problem, you can do one of the following:
Restrict your pset so that it contains only members with the same scope.
If the current process's scope level does not exist in other processes in the set, you can use the up command to move up its call stack to a point where it has a scope level that does exist in the other processes.
If different processes in the set have different scopes, you can issue the up and down commands as needed to ensure that they all have the same scope.
Commands such as pset and process that affect scope print the current function when you issue them.
In scalar Prism, choosing Where from the Debug menu displays the call stack for the program; see " Displaying and Moving Through the Call Stack". A message-passing program, however, can have multiple call stacks, one for each process. To show the relationships among these call stacks, MP Prism provides a Where graph; this window displays a snapshot of the dynamic call graph of the program. Information is displayed for all processes that are not running.
To display the Where graph:
From the menu bar - Choose Where from the Debug menu.
From the command line - Issue the command
where on dedicated
A window like the one shown in Figure 4-5 is displayed.
The Where graph centers on the current process of the current pset--that is, the processes related to it are lined up in a single column. In Figure 4-1, process 0 is the current process. If you change the current process, the Where graph rearranges itself. The default zoom level of the Where graph shows the arguments for the current process.
At the bottom of each box are line numbers indicating where processes branch.
Shift-click in each function's box to display a pop-up window showing the numbers of the processes with this function in their call stack, along with their arguments.
As Figure 4-6 shows, the Where graph can get quite large, so MP Prism provides methods for panning through it and zooming in and out.
The white box in the navigator rectangle at the top of the window shows the position of the display area relative to the entire Where graph. You can either drag the box or click at a spot in the navigator. The box moves to that spot, and the window shows the Where graph in this area of the total display.
To display more of the Where graph at the same time, click on the Zoom down arrow to the right of the navigator. This reduces the size of the boxes representing the functions and removes information. Figure 4-6 shows the Where graph of Figure 4-5, zoomed out one level. Note that the information about the current process's arguments is gone.
Zooming out one more level removes the line numbers, and one more level after that removes the function names, leaving only boxes connected by lines. You can still shift-click on a box to display information about it.
Clicking on the Zoom up arrow increases the size of the function boxes and includes more information in them. Figure 4-7 shows the Where graph of Figure 4-5, zoomed in. In this case, the Where graph shows, for each function, the processes that have that function in their call stack. As in the Psets window, the processes are represented as bitmaps of cells, numbered starting at the upper left, increasing from left to right and then jumping to the next row.
Zooming in another level shows all arguments for all processes.
You can shrink selected portions of the Where graph. This is useful if you want to see the overall structure of the graph, but in addition want to focus on certain functions.
Middle-click on a function to iconify it and all of its children. Middle-click on an iconified function to re-expand it and its children to the current zoom level.
Alternatively, you can click on the (De)iconify Node button next to the Zoom arrows at the top of the Where graph. This changes the mouse pointer to a target. You can then left-click on a function to iconify it and its children. If it is already iconified, left-clicking on it will re-expand it and its children. To cancel the operation, left-click anywhere outside of the boxes surrounding the functions.
When you first display the Where graph, the main function is highlighted. You can left-click on a function to highlight it. Or, you can move through the Where graph via the keyboard:
Use the up arrow key to move to the parent of the highlighted function.
If line numbers are visible in the highlighted function, by default the leftmost number is selected by having a box drawn around it. Use the left and right arrows to select other line numbers in the function. You can then use the down arrow key to highlight the function called at the selected line.
Pressing the spacebar while in the Where graph does the following:
It displays the highlighted function in the source window.
It creates a new current pset, with the same name as the function, and containing the processes with this function in their call stack. The current process of this current set is the lowest-numbered process in the set.
Issuing the where command by default displays (in the history region) the call stack consecutively for each process in the current set (or in the pset you specify via the pset qualifier).
Issuing the command
where on dedicated
displays the Where graph, as described above.
Issuing the command
where on snapshot
puts the history-region output into a window; it does not create a Where graph.
If you use Prism on programs that have been compiled with optimization options, you should expect different behavior from Prism commands and changes in the visibility of variables in the optimized programs.
When the control flow is inside a routine that has been compiled with both -g and an optimization option (a debuggable optimized routine), the next and step commands change their behavior:
next steps out of the current routine and stops in the next debuggable routine that differs from the original routine.
step stops in the next debuggable routine (including recursive calls of the original routine).
You can set breakpoints using the stop at command inside debuggable optimized routines only at the first line of such a routine. If the routine name is foo and the first instruction in foo is ADDR_INSTR then the breakpoint is set as if you had used stop in foo or stopi at ADDR_INSTR.
Note that the following (related) commands are unaffected:
nexti
stepi
stopi
When the control flow returns to a debuggable optimized routine, as a result of one of the following commands:
return
stepout
then Prism assumes that the current position is at the first line of the current routine. Prism makes the same assumption when the source file position (at the command line or in the GUI) is updated as a result of up or down commands ending in a debuggable optimized routine.
Due to the effects of optimization on variable location in executable programs that have been compiled with optimization, not all variables can be accessed by Prism at all times.
The accessibility of variables can be defined by whether the variables can be used in expressions that require the right value of the variable (such as print X, or call foo(X)) or the left value of the variable (such as assign X=1).
The limits of accessibility can be described by the flow of control in an optimized program. When the flow of control is in a routine compiled with both -g and an optimization flag:
If the control flow is at the first machine instruction of the routine (which has not yet been executed), then all global variables and the routine's arguments are accessible. No other local variable is accessible.
If the first machine instruction of the current routine has already been executed, then only the global variables are accessible. No local variable is accessible.
The following commands can use only accessible variables:
where - The where stack will display values only for accessible arguments, and `???' for all the others.
The where command reports all active stack frames which have a stack pointer. The where command does not report routines that have no frame pointer and routines that have been inlined.
You can issue commands in the command window to display the contents of memory addresses and registers.
To display the contents of an address, specify the address on the command line, followed by a slash (/). For example,
0x10000/
If you specify the address as a period, Prism displays the contents of the memory address following the one printed most recently.
Specify a symbolic address by preceding the name with an &. For example,
&x/
prints the contents of memory for variable x. The Prism output, for example, might be
0x000237f8: 0x3f800000
The address you specify can be an expression made up of other addresses and the operators +, -, and indirection (unary *). For example,
0x1000+100/
prints the contents of the location 100 addresses above address 0x1000.
After the slash you can specify how memory is to be displayed. Formats that are supported are listed in Table 4-1.
Table 4-1 Memory Address Formats
Format |
Description |
---|---|
d |
Print a short word in decimal |
D |
Print a long word in decimal |
o |
Print a short word in octal |
O |
Print a long word in octal |
x |
Print a short word in hexadecimal |
X |
Print a long word in hexadecimal |
b |
Print a byte in octal |
c |
Print a byte as a character |
s |
Print a string of characters terminated by a null byte |
f |
Print a single-precision real number |
F |
Print a double-precision real number |
i |
Print the machine instruction |
The initial format is X. If you omit the format in your command, you get either X (if you haven't previously specified a format) or the format you specified previously.
You can print the contents of multiple addresses by specifying a number after the slash (and before the format). For example,
0x1000/8X
displays the contents of eight memory locations starting at address 0x1000. Contents are displayed as hexadecimal long words.
You can examine the contents of registers in the same way that you examine the contents of memory. Specify a register by preceding its name with a dollar sign. For example,
$f0/
prints the contents of the X register.
Specify a number after the slash to print the contents of multiple registers. For example,
$f0/3
prints the contents of registers f0, f1, and f2. The order in which the registers are displayed is that shown in Table 4-1.
You can also specify a format, as described above. The format specifier controls the display of the output; it doesn't affect how much of the register contents is displayed. Thus,
$f0/3X
displays three registers; the output is displayed as hexadecimal longwords.
The registers in the UltraSPARC processor are listed in Table 4-2.
Table 4-2 UltraSPARC Registers
Name |
Register |
---|---|
$g0-$g7 |
Global registers (64 bits) |
$o0-$o7 |
Output registers (64 bits) |
$l0-$l7 |
Local registers |
$i0-$i7 |
Input registers |
$psr |
Processor state register |
$pc |
Program counter |
$npc |
Next program counter |
$y |
Y register |
$wim |
Window invalid mask |
$tbr |
Trap base register |
$f0-$f31 |
Floating-point registers |
$fsr |
Floating status register (64 bits) |
$f0f1-$f62f63 |
Floating-point registers |
$xg0-$xg7 |
Upper 32 bits of $g0-$g7 (SPARC V8 plus only, or higher) |
$xo0-$xo7 |
Upper 32 bits of $o0-$o7 (SPARC V8 plus only, or higher) |
$xfsr |
Upper 32 bits of $fsr (SPARC V8 plus only, or higher) |
$fprs |
Floating-point registers state (SPARC V8 plus only, or higher) |
$tstate |
Trap state register (SPARC V8 plus only, or higher) |
$fp |
Frame pointer (synonym for $i6) |
$sp |
Stack pointer (synonym for $o6) |