Search Results

This guide describes how to use the PGI debugger to debug serial and parallel applications built with PGI Fortran, C, and
C++ compilers for X86, AMD64 and Intel 64 processor-based systems. It contains information about how to use the debugger, as
well as detailed reference information on commands and its graphical interface.

This guide is intended for application programmers, scientists and engineers proficient in programming with the Fortran, C,
and/or C++ languages. The PGI tools are available on a variety of operating systems for the X86, AMD64, and Intel 64 hardware platforms.
This guide assumes familiarity with basic operating system usage.

Your system needs to be running a properly installed and configured
version of this PGI product. For information on installing PGI compilers and tools,
refer to the Release Notes and Installation Guide included with your
software.

is used for filenames, directories, arguments, options, examples, and
for language statements in the text, including assembly language
statements.

Bold

is used for commands.

[ item1 ]

in general, square brackets indicate optional items. In this case
item1 is optional. In the context of p/t-sets, square brackets are
required to specify a p/t-set.

{ item2 | item 3 }

braces indicate that a selection is required. In this case, you must
select either item2 or item3.

filename ...

ellipsis indicate a repetition. Zero or more of the preceding item
may occur. In this example, multiple filenames are allowed.

FORTRAN

Fortran language statements are shown in the text of this guide using
a reduced fixed point size.

C/C++

C/C++ language statements are shown in the test of this guide using a
reduced fixed point size.

The PGI compilers and tools are supported on a wide variety of Linux, macOS
and Windows operating systems running on 64-bit x86-compatible processors,
and on Linux running on OpenPOWER processors. (Currently, the PGI
debugger is supported on x86-64/x64 only.) See the Compatibility and Installation
section on the PGI website
for a comprehensive listing of supported platforms.

Note:
Support for 32-bit development was deprecated in PGI 2016 and is no
longer available as of the PGI 2017 release. PGI 2017 is only
available for 64-bit operating systems and does not include the ability to
compile 32-bit applications for execution on either 32- or 64-bit
operating systems.

The PGI debugger is a symbolic debugger for Fortran, C, C++ and assembly language programs. It provides debugger features, such as execution control using breakpoints, single-stepping,
and examination and modification of application variables, memory locations, and registers.

The debugger supports debugging of certain types of parallel applications:

Multi-threaded and OpenMP applications.

MPI applications.

Hybrid applications, which use multiple threads or OpenMP as well as multiple MPI processes.

Multi-threaded and OpenMP applications may be run using more threads than the available number of CPUs, and MPI applications
may allocate more than one process to a cluster node. The debugger supports debugging the listed types of applications regardless
of how well the number of threads match the number of CPUs or how well the number of processes match the number of cluster
nodes.

Throughout this manual we use several debugging-specific terms. The program is the executable being debugged. The platform is the combination of the operating system and processors(s) on which the program runs. The program architecture is the platform for which the program was built.

Remote debugging introduces a few more terms. Remote debugging is the process of running the debugger on one system (the client) and using it to debug a program running on a different system (the server). Local debugging, by contrast, occurs when the debugger and program are running on the same system. A connection is the set of information the debugger needs to begin debugging a program. This information always includes the program name
and whether debugging will be local or remote.

To build a program for debug, compile with the -⁠g option. With this option, the compiler generates information about the symbols and source files in the program and includes
it in the executable file. The option -⁠g also sets the compiler optimization to level zero (no optimization) unless you specify optimization options such as -⁠O, -⁠fast, or -⁠fastsse on the command line. Optimization options take effect whether they are listed before or after -⁠g on the command line.

Programs built with -⁠g and optimization levels higher than -⁠O0 can be debugged, but due to transformations made to the program during optimization, source-level debugging may not be reliable.
Assembly-level debugging (e.g., accessing registers, viewing assembly code, etc.) is reliable, even with optimized code. Programs
built without -⁠g can be debugged; however, information about types, local variables, arguments and source file line numbers are not available.
For more information on assembly-level debugging, refer to Assembly-Level Debugging.

In programs built with both -⁠g and optimization levels higher than -⁠O0, some optimizations may be disabled or otherwise affected by the -⁠g option, possibly changing the program behavior. An alternative option, -⁠gopt, can be used to build programs with full debugging information, but without modifying program optimizations. Unlike -⁠g, the -⁠gopt option does not set the optimization to level zero.

To build an application for debug on Windows platforms, applications must be linked with the -⁠g option as well as compiled with -⁠g. This process results in the generation of debug information stored in a ‘.dwf’ file and a ‘.pdb’ file. The PGI compiler driver should always be used to link applications; except for special circumstances, the linker should
not be invoked directly.

The GUI, the default user interface, supports command entry through a point-and-click interface, a view of source and assembly
code, a full command-line interface panel, and several other graphical elements and features. There may be minor variations
in the appearance of the GUI from system to system, depending on the type of display hardware available, the settings for
various defaults and the window manager used. Except for differences caused by those factors, the basic interface remains
the same across all systems.

The debugger GUI depends on the Java Virtual Machine (JVM) which is part of the Java Runtime Environment (JRE). The debugger
requires that the JRE be a specific minimum version or above.

Command-line mode debugging does not require the JRE.

Linux and macOS

When PGI software is installed on Linux or macOS, the version of Java required by the debugger is also installed. The debugger
uses this version of Java by default. You can override this behavior in two ways: set your PATH to include a different version
of Java; or, set the PGI_JAVA environment variable to the full path of the Java executable. The following example uses a bash
command to set PGI_JAVA:

$ export PGI_JAVA=/home/myuser/myjava/bin/java

Windows

If an appropriately-versioned JRE is not already on your Windows system, the PGI software installation process installs it
for you. The PGI command shell and Start menu links are automatically configured to use the JRE. If you choose to skip the
JRE-installation step or want to use a different version of Java to run the debugger, then set your PATH to include the Java
bin directory or use the PGI_JAVA environment variable to specify the full path to the java executable.

You can start debugging a program right away by launching the PGI debugger and giving it the program name. For example, to
load your_program into the debugger, do:

$ pgdbg your_program

Now you are ready to set breakpoints and start debugging.

You can also launch the debugger without a program. Once the debugger is up, use the Connections tab to specify the program
to debug. To load the specified program into the debugger, use the Connections tab's Open button.

An initialization file can be useful for defining common aliases, setting breakpoints, and for other startup commands. If
an initialization file named .pgdbgrc exists in the current directory or in your home directory, as defined by the environment variable HOME, the debugger opens
this file when it starts up and executes the commands in it.

If an initialization file is found in the current directory, then the initialization file in the home directory, if there
is one, is ignored. However, a script command placed in the initialization file can be used to execute the initialization file in the home directory or any other
file.

The debugger's default user interface is a graphical user interface or GUI. There may be minor variations in the appearance
of the GUI from host to host, depending on the type of display hardware available, the settings for various defaults and the
window manager used. Except for differences caused by those factors, the basic interface remains the same across all systems.

Figure 1 shows the debugger GUI as it appears when it is invoked for the first time.

The GUI can be resized according to the conventions of the underlying window manager. Changes in window size and other settings
are saved and used in subsequent invocations of the debugger. To prevent changes to the default settings from being saved,
uncheck the Save Settings on Exit item on the Edit menu.

As the illustration shows, the GUI is divided into several areas: the menu bar, main toolbar, source window, program I/O window,
and debug information tabs.

The source window and all of the debug information tabs are dockable tabs. A dockable tab can be separated from the main window
by either double-clicking the tab or dragging the tab off the main window. To return the tab to the main window, double-click
it again or drag it back onto the main window. You can change the placement of any dockable tab by dragging it from one location
to another. Right-click on a dockable tab to bring up a context menu with additional options, including and option to close
the tab. To reopen a closed tab, use the View menu. To return the GUI to its original state, use the Edit menu's Restore Default Settings... option.

The following sections explain the parts of the GUI and how they are used in a debug session.

The source window, illustrated in Figure 2, displays the source code for the current location. Use the source window to control the debug session, step through source
files, set breakpoints, and browse source code.

Figure 2. Source Window

The source window contains a number of visual aids that allow you to know more about the execution of your code. The following
sections describe these features.

Source code debugging is the default unless source information is unavailable in which case debugging will be shown using
disassembly. When debugging in source code, use the View | Show Assembly menu option to switch to assembly-level debugging.
When disassembly is shown, use options on the View menu to toggle on or off the display of source code, assembly addresses,
and bytecode. Source or assembly is always shown for the current process or thread.

Source code line numbers are shown, when known, in their own column to the left of the source or assembly display. A grayed-out
line number indicates a non-executable source line. Some examples of non-executable source lines are comments, non-applicable
preprocessed code, some routine prologues, and some variable declarations. Non-executable source lines can also exist for
otherwise executable code when a program is compiled at certain optimization levels. Breakpoints and other events cannot be
set on non-executable lines.

To the left of the line numbers is another column called the gutter. The gutter is where the program counter and debug events
like breakpoints are shown. The program counter is represented by a blue arrow and shows where program execution is during
a debug session. Breakpoints can be set on executable source lines and any assembly line just by left clicking in the gutter.
A red sphere will appear at the line where the breakpoint was set. To delete a breakpoint, either left click on any red breakpoint
sphere or right click and select the option from the context menu. By right clicking in the gutter at a place without an existing
breakpoint, the context menu will pop up and provide the option of setting a hit count breakpoint. After selecting this option,
a dialog will appear for configuring the hit count number and break condition, i.e. break when the hit count is equal to,
greater than or a multiple of the specified number.

The source window supports a context menu that provides convenient access to commonly used features. Right-click in the source
window to bring up this context menu. If text is selected when the context menu opens, the selection is used by the context
menu options.

In the example in Figure 3, the variable array(i) is highlighted and the context menu is set to print its value as a decimal integer:

Most of the buttons on the main toolbar have corresponding entries on the Debug menu. The functionality invoked from the toolbar
is the same as that achieved by selecting the menu item. Refer to the "Debug Menu" descriptions for details on how Start Debugging (Continue), Stop Debugging, Stop Program, Restart, Step Into, Step Over,
Step Out, and Display Current Location work.

As illustrated in Figure 5, the main toolbar contains four drop-down lists. A drop-down list displays information while also offering an opportunity
to change the displayed information if other choices are available. When no or one choice is available, a drop-down list is
grayed-out. When more than one choice is available, the drop-down arrow in the component can be clicked to display the available
choices.

Figure 5. Drop-Down Lists on Toolbar

Current Process or Current Thread

The first drop-down list displays the current process or current thread. The list’s label changes depending on whether processes
or threads are described. When more than one process or thread is available, use this drop-down list to specify which process
or thread should be the current one. The current process or thread controls the contents of the source and disassembly display
tabs. The function of this drop-down list is the same as that of the Procs & Threads tab in the debug information tabs.

Apply

The second drop-down list is labeled Apply. The selection in the Apply drop-down determines the set of processes and threads
to which action commands are applied. Action commands are those that control program execution and include, for example, cont, step, next, and break. By default, action commands are applied to all processes and threads. When more than one process or thread exists, you have
additional options in this drop-down list from which to choose. The Current Group option designates the process and thread
group selected in the Groups tab, and the Current Process and Current Thread options designate the process or thread selected
in the Current Process or Current Thread drop-down.

Display

The third drop-down list is labeled Display. The selection in the Display drop-down determines the set of processes and threads
to which data display commands are applied. Data display commands are those that print the values of expressions and program
state and include, for example, print, names, regs and stack. The options in the Display drop-down are the same as those in the Apply drop-down but can be changed independently.

File

The fourth drop-down list is labeled File. It displays the source file that contains the current target location. It can be
used to select another file for viewing in the source window.

Debug information tabs take up the lower half of the debugger GUI. Each of these tabs provides a particular function or view
of debug information. The following sections discuss the tabs as they appear from left-to-right in the GUI’s default configuration.

The Groups tab displays the current set of user-defined groups of processes and threads. The group selected (highlighted)
in the Groups tab defines the Current Group as used by the Apply and Display drop-down lists. In the following illustration,
the ‘evens’ group is the Current Group.

Figure 9. Groups Tab

To change the set of defined groups use the Add..., Modify..., and Remove... buttons on the Groups tab.

A connection is the set of information the debugger needs to begin debugging a program. The Connections tab provides the interface to
specifying information for a particular connection, and allows you to create and save multiple connections. Saved connections
persist from one invocation of the debugger to the next. When you launch the debugger, the Default connection is created for
you. If you launched the debugger with an executable, the Program field is filled in for you.

Figure 10. Connections Tab

Fields required by the debugger for program launch are bold. Fields not applicable to the current configuration options are grayed-out. To display a tooltip describing the use of a
field, hover over its name.

The Memory tab displays a region of memory starting with a provided Address which can be a memory address or a symbol name.
One element of memory is displayed by default, but this amount can be changed via the Count field. Figure 14 illustrates this process.

Figure 14. Memory Tab

The default display format for memory is hexadecimal. The display format can be changed by providing a printf-like format
descriptor in the Format field. A detailed description of the supported format strings is available in Memory Access in Command Reference.

The MPI Messages tab provides a listing of the MPI message queues as illustration in Figure 16.

Figure 16. MPI Messages Tab

Message queue information applies only to MPI applications. When debugging a non-MPI application, this tab is empty. Additionally,
message queue information is not supported by Microsoft MPI so this tab contains no data on Windows.

The Procs & Threads tab provides a graphical display of the processes
and threads in a debug session.

The Process Grid in Figure 17 has
four processes. The thicker border around process 0 indicates that it is
the current process; its threads are represented pictorially. Thread 0.0,
as the current thread of the current process, has the thickest
border. Clicking on any process or thread in this grid changes that
process or thread to be the current process or thread.

Figure 17. Process (Thread) Grid Tab

Use the slider at the bottom of the grid to zoom in and out.

The color
of each element
indicates the state of that process or thread. For a list of colors and
states, refer to Table 1.

The target machine’s architecture determines the number and type of system registers. Registers are organized into groups
based on their type and function. Each register group is displayed in its own tab contained in the Registers tab. Registers
and their values are displayed in a table. Values are shown for all the threads of the currently selected process.

In Figure 18, the General Purpose registers are shown for threads 0-3 of process 0.

Figure 18. General Purpose Registers

The values in the registers table are updated each time the program stops. Values that change from one stopping point to the
next are highlighted in yellow.

Register values can be displayed in a variety of formats. The formatting choices provided for each register group depends
on the type of registers in the group. Use the Format drop-down list to change the displayed format.

Vector registers, such as XMM and YMM registers, can be displayed in both scalar and vector modes. Change the Mode drop-down
list to switch between these two modes.

The Status tab provides a text summary of the status of the program being debugged. The state and location of each thread
of each process is shown. In Figure 19, each of four processes has two threads.

The main menu bar contains these menus: File, Edit, View, Connections, Debug and Help. This section describes these menus
and their contents.

You can navigate the menus using the mouse or the system’s mouseless modifier (typically the Alt key). Use the mouseless modifier
together with a menu’s mnemonic, usually a single character, to select a menu and then a menu item. Menu mnemonics are indicated
with an underscore. For example, the File menu appears as File which indicates that ‘F’ is the mnemonic.

Keyboard shortcuts, such as Ctrl+V for Edit | Paste, are available for some actions. Where a keyboard shortcut is available,
it is shown in the GUI on the menu next to the menu item.

Menu items that contain an ellipsis (...) launch a dialog box to assist in performing the menu’s action.

Restore the GUI to the state that it was in at the start of the debug session.

Save Settings on Exit

By default, the debugger saves the state (size and settings) of the GUI on exit on a per-system basis. To prevent settings
from being saved from one invocation of the debugger to another, uncheck this option. This option must be unchecked prior
to every exit since the debugger always defaults to saving the GUI state.

Toggle (turn on or off) the display of assembly code during a debug session. Source code can be shown only when source information
is available.

Disable/Enable Syntax Coloring

Toggle syntax coloring of source code.

Hide Source in Assembly/Add Source to Assembly

When assembly code is shown, toggle the display of source code (when available).

Hide Addresses/Show Addresses

When assembly code is shown, toggle the display of assembly addresses.

Show Bytecode/Hide Bytecode

When assembly code is shown, toggle the display of assembly bytecode.

Registers

The Registers menu item opens a submenu containing items representing every subtab on the Registers tab. Recall that each
subtab represents a register group and the set of register groups is system and architecture dependent. Use the Registers
submenu to hide or show tabs for register groups. Use the Show Selected item to hide or show the Registers tab itself.

Font...

Use the font chooser dialog box to select the font and size used in the source window and debug information tabs. The default
font is named monospace and the default size is 12.

Show Tool Tips

Tool tips are small temporary messages that pop up when the mouse pointer hovers over a component in the GUI. They provide
additional information on the functionality of a component. Tool tips are enabled by default. Uncheck the Show Tools Tips
option to prevent them from popping up.

Use the items under this menu to manage the connections displayed in the Connections list on the Connections tab.

Connect Default

Open the currently displayed connection. When the debugger starts, this connection is named ‘Default.’ When a different connection
is selected, the name of this menu option changes to reflect the name of the selected connection. This menu option works the
same way that the Open button on the Connections tab works.

Stop the running program. This action halts the running processes or threads. For more information, refer to the halt command.

Stop Debugging

Stop debugging the program.

Restart Program

Start the program from the beginning.

Step

Continue and stop after executing one source line or one assembly-level instruction depending on whether source or assembly
is displayed. Step steps into called routines. For more information, refer to the step and stepi commands.

Next

Continue and stop after executing one source line or one assembly-level instruction depending on whether source or assembly
is displayed. Next steps over called routines. For more information, refer to the next and nexti commands.

Step Out

Continue and stop after returning to the caller of the current routine. For more information, refer to the stepout command.

Set Breakpoint...

Set a breakpoint at the first executable source line in the specified routine.

Call Routine

Specify a routine to call. For more information, refer to the call command.

Display Current Location

Display the current program location in the Source panel. For more information, refer to the arrive command.

Up

Enter the scope of the routine up one level in the call stack. For more information, refer to the up command.

Down

Enter the scope of the routine down one level in the call stack. For more information, refer to the down command.

Custom

Opens a separate window where you can enter a variety of debugger commands.

The optional arguments may be any of the command-line arguments described in this chapter. The program parameter is the name of the executable file being debugged. The optional arguments arg1 arg2 ... argn are the command-line arguments to the program.

Debug an MPI program. Here the term launcher means the MPI launch program. The debugger uses mpiexec as the default launcher. If the location of the launcher in your MPI distribution is not in your PATH environment variable,
you must provide the debugger with the full path to the launcher, including the name of the launch tool itself. If the location
of the launcher is in your PATH, then you just need to provide the name of the launcher, and then only if the launcher is
not mpiexec.

-⁠sgimpi[=<launcher_path>]

Debug an SGI MPI (MPT) program. The debugger uses mpirun as the default launcher for SGI MPI debugging. If the location of mpirun in your installation of SGI MPI is not in your PATH environment variable, you must provide the debugger with the full path
to mpirun, including the name mpirun itself. If the location of mpirun is in your PATH, then you can use -⁠sgimpi without a sub-option.

-⁠program_args

Pass subsequent arguments to the program under debug; required when passing program arguments to an MPI program.

The debugger supports a command language that is capable of evaluating complex expressions. The command language is composed
of commands, constants, symbols, locations, expressions, and statements.

You can use the command language by invoking the debugger's command-line interface with the -⁠text option, or in the Command tab of the debugger's graphical user interface, as described in The Graphical User Interface.

In dbx mode, the debugger uses commands compatible with the Unix-based dbx debugger.

PGI and dbx commands are available in both command modes, but some command behavior may be slightly different depending on
the mode. The mode can be set while the debugger is running by using the pgienv command.

The debugger uses the symbolic information contained in the executable object file to create a symbol table for the target
program. The symbol table contains symbols to represent source files, subroutines, types (including structure, union, pointer,
array, and enumeration types), variables, and arguments. The debugger's command-line interface is case-sensitive with respect
to symbol names; a symbol name on the command line must match the name as it appears in the object file.

Since several symbols in a single application may have the same name, scope rules are used to bind program identifiers to
symbols in the symbol table. The debugger uses the concept of a search scope for looking up identifiers. The search scope
represents a subroutine, a source file, or global scope. When the user enters a name, the debugger first tries to find the
symbol in the search scope. If the symbol is not found, the containing scope (source file or global) is searched, and so forth,
until either the symbol is located or the global scope is searched and the symbol is not found.

Normally, the search scope is the same as the current scope, which is the subroutine where execution is currently stopped.
The current scope and the search scope are both set to the current subroutine each time execution of the program stops. However,
you can use the enter command to change the search scope.

A scope qualifier operator @ allows selection of out-of-scope identifiers. For example, if f is a routine with a local variable
i, then:

f@i

represents the variable i local to f. Identifiers at file scope can be specified using the quoted file name with this operator.
The following example represents the variable i defined in file xyz.c.

To provide access to the system registers, the debugger maintains symbols for them. Register names generally begin with $
to avoid conflicts with program identifiers. Each register symbol has a default type associated with it, and registers are
treated like global variables of that type, except that their address may not be taken. For more information on register symbols,
refer to SSE Register Symbols.

Some commands must refer to source code
locations. Source file names must be enclosed in double quotes. Source
lines are indicated by number, and may be qualified by a quoted filename
using the scope qualifier operator. Further, a range of lines is indicated
using the range operator ":".

Here are some examples:

break 37

sets a breakpoint at line 37 of the current source file.

break "xyz.c"@37

sets a breakpoint at line 37 of the source file xyz.c.

list 3:13

lists lines 3 through 13 of the current file.

list "xyz.c"@3:13

lists lines 3 through 13 of the source file xyz.c.

Some commands
accept both line numbers and addresses as arguments. In these commands, it
is not always obvious whether a numeric constant should be interpreted as
a line number or an address. The description for these commands says which
interpretation is used. However, the debugger provides commands to convert
from source line to address and vice versa. The line
command converts an address to a line, and the addr
command converts a line number to an address.

Line numbers are used to name lexical blocks. The line number of the first instruction contained by a lexical block is used
to indicate the start scope of the lexical block.

In the following example, there are two variables named var. One is declared in function main, and the other is declared in
the lexical block starting at line 5. The lexical block has the unique name "lex.c"@main@5. The variable var declared in "lex.c"@main@5
has the unique name "lex.c"@main@5@var. The output of the whereis command that follows shows how these identifiers can be distinguished.

Although the debugger's command-line input is processed one line at a time, statement constructs allow multiple commands per
line, as well as conditional and iterative execution. The statement constructs roughly correspond to the analogous C language
constructs. Statements may be of the following forms.

Simple Statement: A command and its arguments. For example:

print i

Block Statement: One or more statements separated by semicolons and enclosed in curly braces. Note: these may only be used as arguments to
commands or as part of if or while statements. For example:

if(i>1) {print i; step }

If Statement: The keyword if, followed by a parenthesized expression, followed by a block statement, followed by zero or more else if clauses, and at most one else clause. For example:

if(i>j) {print i} else if(i<j) {print j} else {print "i==j"}

While Statement: The keyword while, followed by a parenthesized expression, followed by a block statement. For example:

while(i==0) {next}

Multiple statements may appear on a line separated by a semicolon. The following example sets breakpoints in routines main
and xyz, continues, and prints the new current location.

break main; break xyz; cont; where

However, since the where command does not wait until the program has halted, this statement displays the call stack at some arbitrary execution point
in the program. To control when the call stack is printed, insert a wait command, as shown in this example:

break main; break xyz; cont; wait; where

Note:

Any value returned by the last statement on a line is printed.

Statements can be parallelized across multiple threads of execution. For more information, refer to Parallel Statements.

The
debugger supports six basic commands for defining events. Each command
takes a required argument and may also take one or more optional
arguments. The basic commands are break,
watch, hwatch, trace,
track, and do.

Event Command Descriptions

The break
command takes an argument specifying a breakpoint
location. Execution stops when that location is reached.

The watch
command takes an expression argument. Execution stops and the new
value is printed when the value of the expression changes.

The hwatch
command takes a data address argument, which can be either an
identifier or a variable name. Execution stops when memory at that
address is written.

The trace
command activates source line tracing, as specified by the arguments
you supply.

The track
command is like watch except that execution
continues after the new value is printed.

The do command
takes a list of commands as an argument. The commands are executed
whenever the event occurs.

Event Command Arguments

The six event commands share a common set of optional arguments. The
optional arguments provide the ability to make the event definition more
specific. They are:

at line

Event occurs at indicated line.

at addr

Event occurs at indicated address.

in routine

Event occurs throughout indicated routine.

if (condition)

Event occurs only when condition is true.

do {commands}

When event occurs, execute commands.

The optional arguments may appear in any order after the required
argument and should not be delimited by commas.

Event Command Examples

Here are some event definition examples:

watch i at 37 if(y>1)

This event definition says to stop and print the value of i
whenever line 37 is executed and the value of y is greater
than 1.

do {print xyz} in f

This event definition says that at each line in the routine f
print the value of xyz.

break func1 if (i==37)
do {print a[37]; stack}

This event definition says to print the value of a[37] and do
a stack trace when i is equal to 37 in routine func1.

Event commands that do not explicitly define a location occur at each
source line in the program. Here are some examples:

do {where}

prints the current location at the start of each source line.

trace a.b

prints the value of a.b each time the value has changed.

track a.b

prints the value of a.b at the start of each source line if
the value has changed.

Note:
Events that occur at every
line can be useful, but they can make program execution very
slow. Restricting an event to a particular address minimizes the impact
on program execution speed, and restricting an event that occurs at
every line to a single routine causes execution to be slowed only when
that routine is executed.

The debugger supports instruction-level versions of several commands,
such as breaki, watchi,
tracei, tracki, and
doi. The basic difference in the instruction-level
version is that these commands interpret integers as addresses rather
than line numbers, and events occur at each instruction rather than at
each line.

When multiple
events occur at the same location, all event actions are taken before
the prompt for input. Defining event actions that resume execution is
allowed but discouraged, since continuing execution may prevent or
defer other event actions.

For example, the following syntax creates an ambiguous situation:

break 37 do {continue}
break 37 do {print i}

With this sequence, it is not clear whether i
will ever be printed.

Events only occur after the continue and
run commands. They are ignored by
step, next, call,
and other commands.

Identifiers and line numbers in events are bound to the current scope
when the event is defined.

For example, the following command sets a breakpoint at line 37 in the
current file.

break 37

The following command tracks the value of whatever variable
i is currently in scope.

track i

If i is a local variable, then it is wise to add
a location modifier (at or in) to restrict the event to a scope where
i is defined. Scope qualifiers can also specify lines or variables
that are not currently in scope. Events can be parallelized across
multiple threads of execution. See Parallel Events for details.

If the program is not running, Ctrl+C can be used to interrupt long-running debugger commands. For example, a command requesting
disassembly of thousands of instructions might run for a long time, and it can be interrupted by Ctrl+C. In such cases the
program is not affected.

If the program is running, entering Ctrl+C at the debugger command prompt halts execution of the program. This is useful in
cases where the program ‘hangs’ due to an infinite loop or deadlock.

Sending Ctrl+C, also known as SIGINT, to a program while it is in the middle of initializing its threads, by calling omp_set_num_threads()
or entering a parallel region, may kill some of the threads if the signal is sent before each thread is fully initialized.
Avoid sending SIGINT in these situations. Note that when the number of threads employed by a program is large, thread initialization
may take a while.

Sending Ctrl+C to a running MPICH1 program, support for which is now deprecated, is not recommended. For details, refer to
Use halt instead of Ctrl+C. Use the debugger's halt command as an alternative to sending Ctrl+C to a running program. The debugger's command prompt must be available in order
to issue a halt command. The command prompt is available while threads are running if pgienv threadwait none is set.

As described in Using Continue, when debugging an MPI job via the following command, the debugger spawns the job in a manner that prevents console-generated
interrupts from directly reaching the MPI launcher or any of the MPI processes.

$ pgdbg -mpi ...

In this case, typing Ctrl+C only interrupts the debugger, leaving the MPI processes running. When debugger's thread wait mode
is not set to none, you can halt the MPI job after using Ctrl+C by entering the debugger's halt command, even if no command prompt is generated.

The command sections that follow use these conventions for the command names and arguments, when the command accepts one.

Command names may be abbreviated by omitting the portion of the command name enclosed in brackets ([]).

Argument names are chosen to indicate what kind of argument is expected.

Arguments enclosed in brackets([]) are optional.

Two or more arguments separated by a vertical line (|) indicate that any one of the arguments is acceptable.

An ellipsis (...) indicates an arbitrarily long list of arguments.

Other punctuation (commas, quotes, etc.) should be entered as shown.

For example, the following syntax indicates that the command list may be abbreviated to lis, and that it can be invoked without any arguments or with one of the following arguments: an integer count, a line range, a routine name, or a line and a count.

[line | routine ] [if (condition)] [do {commands}] [hit [>|*] <num>]
When arguments are specified, sets a breakpoint at the indicated line or routine. When no arguments are specified, prints
the current breakpoints.

[addr | routine ] [if (condition)] [do {commands}] [hit [>|*]
<num>]
When arguments are specified, sets a breakpoint
at the indicated address or routine. When no arguments are
specified, prints the current breakpoints.

event-number | all | 0 | event-number [,.event-number.]Delete the event event-number or all events (delete 0 is the same as delete all). Multiple event numbers can be supplied if they are separated by commas.
Use delete without arguments to list events by event-number.

regs [-info] [-grp=grp1[,grp2...]] [-fmt=fmt1[,fmt2...]] [-mode=vector|scalar]Print a formatted display of the names and values of registers. Specify the register group(s) with the -⁠grp option and formatting with the -⁠fmt option. Use -⁠info to see a listing of available register groups and formats.

[arg0 arg1 ... argn] [< inputfile] [> outputfile]Execute program from the beginning. If arguments arg0, arg1, and so on are specified, they are set up as the command-line
arguments of the program. Otherwise, the arguments for the previous run command are used.

[arg0 , arg1, ... argn]Fork a shell (defined by $SHELL) and give it the indicated arguments (the default shell is sh). Without arguments, invokes
an interactive shell, and executes until a "^D" is entered.

[number]Set the current thread to the thread identified by number; where number is a logical thread ID in the current process’ active
thread list. When issued with no argument, list the current program location of the currently active thread.

expression [at line | in routine] [if (condition)] [do {commands}] Define a watch event. The given expression is evaluated, and subsequently, each time the value of the expression changes,
the program stops and the new value is printed.

This chapter provides information about assembly-level debugging, including an overview about what to expect if you are using
assembly-level debugging or if you did not compile your program for debugging.

The PGI debugger supports debugging regardless of how a
program was compiled. In other words, the debugger does not require that
the program under debug be compiled with debugging information, such as
using -⁠g. It can debug code that is lacking
debug information, but because it is missing information about symbols and
line numbers, it can only access the program at the assembly level. The
debugger also supports debugging at the assembly level if debug symbols
are available.

As described in Building Applications for
Debug, the richest debugging experience is available when the
program is compiled using -⁠g or
-⁠gopt with no optimization. When a program
is compiled at higher levels of optimization, less information about
source-level symbols and line numbers is available, even if the program
was compiled with -⁠g or
-⁠gopt. In such cases, if you want to find
the source of a problem without rebuilding the program, you may need to
debug at the assembly level.

If a program has been "stripped" of all symbols,
either by the linker or a separate utility, then debugging will be at the
assembly level. The debugger is only able to examine or control the
program in terms of memory addresses and registers.

When applications are built without
-⁠g on Windows systems, the resulting binary,
the .exe file, does not contain any symbol
information. The Microsoft linker stores symbol information in a program
database, a .pdb file. To generate a
.pdb file using the PGI compiler drivers, you must
use -⁠g during the link step. You can do this
even if you did not use -⁠g during the compile
step. Having this .pdb file available provides the
debugger with enough symbol information to map addresses to routine names.

To refer to Fortran symbol names when debugging at the assembly level, you must translate names so these match the calling
convention in use by the compiler. For code compiled by the PGI compilers, in most cases this means translating Fortran names
to lower case and appending an underscore. For example, a routine that appears in the source code as "VADD" would be referred to in the debugger as "vadd_".

Note:

Name translation is only necessary for assembly-level debugging. When debugging at the source level, you may refer to symbol
names as they appear in the source.

A special symbol, MAIN_, is created by PGFORTRAN to refer to the main program. PGFORTRAN generates this special symbol whether or not there is a
PROGRAM statement. One way to run to the beginning of a Fortran program is to set a breakpoint on MAIN_, then run.

C++ symbol names are "mangled" names. For the names of C++ methods, the names are modified to include not only the name as it appears in the source code, but information about the
enclosing class hierarchy, argument and return types, and other information. The names are long and arcane. At the source
level these names are translated by the debugger to the names as they appear in the source. At the assembly level, these names
are in the mangled form. Translation is not easy and not recommended. If you have no other alternative, you can find information
about name mangling in the PGI Compiler User's Guide.

This section describes some basic operations for assembly-level debugging using the PGI debugger GUI. If you encounter the
message “Can’t find main function compiled -g” on startup, assembly-level debugging is required.

To get into a program in this situation, you can select the Debug | Set Breakpoint... menu option. For example, to stop at
program entry, in Fortran you could enter MAIN_ in response to the dialog query, while in C or C++ you could enter main.

Debug information tabs that are useful in assembly-level debugging include the Call Stack, Memory, and Register tabs. Disassembly
is automatically shown in the source pane when source files are available. You can also switch from source to disassembly
debugging by selecting the View | Show Assembly menu option.

This section describes some basic operations for assembly-level debugging using the PGI debugger's command-line interface.
When you invoke the debugger's CLI and are presented with a message telling you that "NOTE: Can't find main function compiled -g", assembly-level debugging is required.

To get into the program, you can set a breakpoint at a named routine. To stop at program entry, for example, in Fortran you
could use

pgdbg> break MAIN_

and in C/ C++ you could use

pgdbg> break main

Some useful commands for assembly-level debugging using the debugger's command-line interface include:

Each SSE register may contain four 32-bit single-precision or two 64-bit
floating-point values. The regs command reports these
values individually in both hexadecimal and floating-point format. The
debugger provides command notation to refer to these values individually
or all together.

The component values of each SSE register can be accessed using the same
syntax that is used for array subscripting. Pictorially, the SSE registers
can be thought of as follows:

[32-bit]

127

96

95

64

63

32

31

0

$xmm0[3]

$xmm0[2]

$xmm0[1]

$xmm0[0]

$xmm1[3]

$xmm1[2]

$xmm1[1]

$xmm1[0]

$xmm2[3]

$xmm2[2]

$xmm2[1]

$xmm2[0]

To access $xmm0[3], the 32-bit single-precision floating point value that
occupies bits 96–127 of SSE register 0, use the following command:

pgdbg> print $xmm0[3]

To set $xmm2[0] to the value of $xmm3[2], use the following command:

pgdbg> set $xmm2[0]=$xmm3[2]

[64-bit]

127

64

63

0

$xmm0d[1]

$xmm0d[0]

$xmm1d[1]

$xmm1d[0]

$xmm2d[1]

$xmm2d[0]

To access the 64-bit floating point values in xmm0, append the character
'd' (for double precision) to the register name and
subscript as usual, as illustrated in the following commands:

pgdbg> print $xmm0d[0]

pgdbg> print $xmm0d[1]

In most cases, the debugger detects when the target environment supports
SSE registers. In the event the debugger does not allow access to SSE
registers on a system that should have them, set the
PGDBG_SSE environment variable to
on to enable SSE support.

Fortran array subscripts and ranges are accessed using the Fortran language syntax convention, denoting subscripts with parentheses
and ranges with colons.

PGI compilers for the linux86-64 platform (Intel 64 or AMD64) support large arrays (arrays with an aggregate size greater
than 2GB). You can enable large array support by compiling using these options:-⁠mcmodel=medium -⁠Mlarge_arrays. The debugger provides full support for large arrays and large subscripts.

The debugger supports arrays with non-default lower bounds. Access to such arrays uses the same subscripts that are used in
the program.

The debugger also supports adjustable arrays. Access to adjustable arrays may use the same subscripting that is used in the
program.

In general, the debugger uses C language style
operators in expressions and supports the Fortran
array index selector “()” and the Fortran field selector
“%” for derived types. However, .eq.,
.ne., and so forth are not supported. You must use
the analogous C operators ==, !=, and so on, instead.

Note:

The precedence of operators matches the C language, which may in some
cases be different than that used in Fortran.

Each subprogram that defines a common block has a local static variable symbol to define the common. The address of the variable
is the address of the common block. The type of the variable is a locally-defined structure type with fields defined for each
element of the common block. The name of the variable is the common block name, if the common block has a name, or _BLNK_
otherwise.

For each member of the common block, a local static variable is declared which represents the common block variable. Thus
given declarations:

A module procedure is a subroutine contained within a module. A module procedure itself can contain internal procedures. The
scoping operator @ can be used when working with these types of subprograms to prevent ambiguity.

To use the call command to call a C++ instance method, the object must be explicitly passed as the first parameter to the call. For example, suppose you were given
the following definition of class Person and the appropriate implementation of its methods:

The debugger uses the forward slash character (/) internally as the path component separator on all platforms. The backslash
(\) is used as the escape character in the debugger's command language.

On Windows systems, use backslash as the path component separator in the fields of the Connections tab. Use the forward slash
as the path component separator when using a debugger command in the Command tab or in the CLI. The forward slash separator
convention is still in effect when using a drive letter to specify a full path. For example, to add the Windows pathname C:/Temp/src to the list of searched source directories, use the command:

pgdbg> dir C:/Temp/src

To set a breakpoint at line 10 of the source file specified by the relative path sub1\main.c, use this command:

The debugger supports debugging of core files on Linux platforms. In the GUI, select the Core option on the Connections tab
to enable core file debugging. Fill in the Program and Core File fields and open the connection to load the core file.

You can also start core file debugging from the command line. To do this, use the following options:

$ pgdbg -⁠core coreFileName programName

Core files (or core dumps) are generated when a program encounters an exception or fault. For example, one common exception
is the segmentation violation, which can be caused by referencing an invalid memory address. The memory and register states
of the program are written into a core file so that they can be examined by a debugger.

The shell environment in which the application runs must be set up to allow core file creation. On many systems, the default
user setting ulimit does not allow core file creation.

Check the ulimit as follows:

For sh/bash users:

$ ulimit -c

For csh/tcsh users:

% limit coredumpsize

If the core file size limit is zero or something too small for the application, it can be set to unlimited as follows:

For sh/bash users:

$ ulimit -c unlimited

For csh/tcsh users:

% limit coredumpsize unlimited

See the Linux shell documentation for more details. Some versions of Linux provide system-wide limits on core file creation.

The core file is normally written into the current directory of the faulting application. It is usually named core or core.pid where pid is the process ID of the faulting thread. If the shell environment is set correctly and a core file is not generated in the
expected location, the system core dump policy may require configuration by a system administrator.

Different versions of Linux handle core dumping slightly differently. The state of all process threads are written to the
core file in most modern implementations of Linux. In some new versions of Linux, if more than one thread faults, then each
thread’s state is written to separate core files using the core.pid file naming convention previously described. In older versions of Linux, only one faulting thread is written to the core
file.

If a program uses dynamically shared objects (i.e., shared libraries named lib*.so), as most programs on Linux do, then accurate
core file debugging requires that the program be debugged on the system where the core file was created. Otherwise, slight
differences in the version of a shared library or the dynamic linker can cause erroneous information to be presented by the
debugger. Sometimes a core file can be debugged successfully on a different system, particularly on more modern Linux systems,
but you should take care when attempting this.

When debugging core files, the debugger:

Supports all non-control commands.

Performs any command that does not cause the program to run.

Generates an error message in for any command that causes the program to run.

May provide the status of multiple threads, depending on the type of core file created.

The debugger intercepts all signals sent to any of the threads in a multi-threaded program and passes them on according to
that signal's disposition as maintained by (see the catch and ignore commands), except for signals that cannot be intercepted or signals used by the debugger internally.

SIGTRAP and SIGSTOP are used by Linux for communication of application events to the debugger. Management of these signals
is handled internally. Changing the disposition of these signals in the debugger (via catch and ignore) results in undefined behavior.

Some Linux thread libraries use SIGRT1 and SIGRT3 to communicate among threads internally. Other Linux thread libraries, on
systems that do not have support for real-time signals in the kernel, use SIGUSR1 and SIGUSR2. Changing the disposition of
these signals in the debugger (via catch and ignore) results in undefined behavior.

Target applications compiled with the options -⁠pg or profiled with pgprof generate numerous SIGPROF signals. Although SIGPROF can be handled via the ignore command, debugging of applications built for sample-based profiling is not recommended.

The debugger is a parallel application debugger capable of debugging multi-process MPI applications, multi-thread and OpenMP
applications, and hybrid multi-thread/multi-process applications that use MPI to communicate between multi-threaded or OpenMP
processes.

Because the debugger can debug multi-threaded, multi-process, and hybrid multi-threaded/multi-process applications, it provides
a convention for uniquely identifying each thread in each process. This section gives a brief overview of this naming convention
and how it is used to provide adequate background for the subsequent sections. A more detailed discussion of this convention,
including advanced techniques for applying it, is provided in Thread and Process Grouping and Naming.

The debugger identifies threads in an OpenMP application using the OpenMP thread IDs. Otherwise, the debugger assigns arbitrary
IDs to threads, starting at zero and incrementing in order of thread creation.

The debugger identifies processes in an MPI application using MPI rank (in communicator MPI_COMM_WORLD). Otherwise, the debugger
assigns arbitrary IDs to processes; starting at zero and incrementing in order of process creation. Process IDs are unique
across all active processes.

In a multi-threaded/multi-process application, each thread can be uniquely identified across all processes by prefixing its
thread ID with the process ID of its parent process. For example, thread 1.4 identifies the thread with ID 4 in the process
with ID 1.

An OpenMP application logically runs as a collection of threads with a single process, process 0, as the parent process. In
this context, a thread is uniquely identified by its thread ID. The process ID prefix is implicit and optional. For more information
on debugging threads, refer to Thread-only Debugging.

An MPI program logically runs as a collection of processes, each made up of a single thread of execution. Thread 0 is implicit
to each MPI process. A process ID uniquely identifies a particular process, and thread ID is implicit and optional. For more
information on process debugging, refer to Process-only Debugging.

A hybrid, or multilevel, MPI/OpenMP program requires the use of both process and thread IDs to uniquely identify a particular
thread. For more information on multilevel debugging, refer to Multilevel Debugging.

A serial program runs as a single thread of execution, thread 0, belonging to a single process, process 0. The use of thread
IDs and process IDs is allowed but unnecessary.

Enter threads-only mode to debug a program with a single multi-threaded process. As a convenience the process ID portion can
be omitted. The debugger automatically enters threads-only debug mode from serial debug mode when it detects and attaches
to new threads.

Enter process-only mode to debug an application consisting of single-threaded processes. As a convenience, the thread ID portion
can be omitted. The debugger automatically enters process-only debug mode from serial debug mode when multiple processes are
detected.

The name of a thread in multilevel debug mode is the thread ID prefixed with its parent process ID. This forms a unique name
for each thread across all processes. This naming scheme is valid in all debug modes. The debugger changes automatically to
multilevel debug mode when at least one MPI process creates multiple threads.

Table 7. Thread IDs in Multilevel Debug Mode

0.1

Thread 1 of process 0

0.*

All threads of process 0

*

All threads of all processes

In multilevel debugging, mode status and error messages are prefixed with process/thread IDs depending on context.

You use a process/thread set (p/t-set) to restrict a debugger command to apply to a particular set of threads. A p/t-set is
a set of threads drawn from all threads of all processes in the target program. Use p/t-set notation to define a p/t-set.

In the following sections, you will notice frequent references to three named p/t-sets:

The target p/t-set is the set of processes and threads to which a debugger command is applied. The target p/t-set is initially defined by the
debugger to be the set [all] which describes all threads of all processes.

A prefix p/t-set is defined when p/t-set notation is used to prefix a debugger command. For the prefixed command, the target p/t-set is the
prefix p/t-set.

The current p/t-set is the p/t set currently set in the debugger's environment. You can use the focus command to define the current p/t-set. Unless a prefix p/t-set overrides it, the current p/t set is used as the target p/t-set.

The defset command can be used to define both dynamic and static p/t-sets.

Defining a Dynamic p/t-set

The members of a dynamic p/t-set are those active threads described by the p/t-set at the time that the p/t-set is used. By
default, a p/t-set is dynamic. Threads and processes are created and destroyed as the target program runs and, therefore,
membership in a dynamic set varies as the target program executes.

defset clients [*.1:3]

Defines a dynamic named set ‘clients’ whose members are threads 1, 2, and 3 of all processes that are currently active whenever ‘clients’ is used. Membership in clients changes as processes are created and destroyed.

Defining a Static p/t-set

Membership in a static set is fixed when it is defined. The members of a static p/t-set are those threads described by that
p/t-set when it is defined. Use a ‘!’ to specify a static set.

defset clients [!*.1:3]

Defines a state named set ‘clients’ whose members are threads 1, 2, and 3 of those processes that are currently active at the time of the definition.

Note:

p/t-sets defined with defset are not mode-dependent and are valid in any debug mode.

The current p/t-set is set by the focus command. The current p/t-set is described by the debugger prompt and depends on debug mode. For a description of the command
prompt, refer to The Command Prompt. You can use a p/t-set to prefix a command that overrides the current p/t-set. The prefix p/t-set becomes the target p/t-set
for the command. The target p/t-set defines the set of threads that will be affected by a command.

In the following command line, the target p/t-set is the current p/t-set:

pgdbg [all] 0.0> cont
Continue all threads in all processes

In contrast, a prefix p/t-set is used in the following command so that the target p/t-set is the prefix p/t-set, shown in
this example in bold:

In both of the above examples, the current p/t-set is the debugger-defined set [all]. In the first case, [all] is the target
p/t-set. In the second case, the prefix p/t-set overrides [all] and becomes the target p/t-set. The continue command is applied to all active threads in the target p/t-set. Also, using a prefix p/t-set does not change the current
p/t-set.

To modify an existing p/t-set, select the desired group in the Group table and click the Modify... button. You see a dialog
box similar to that in Figure 21, except that the Group Name and Composition fields contain the selected group’s name and p/t-set respectively. You can edit
the information in these fields and click OK to save the changes.

For the purpose of parallel debugging, the debugger's command set is divided into three disjoint subsets according to how
each command reacts to the current p/t-set. Process level and thread level commands can be parallelized. Global commands cannot
be parallelized.

The following
commands are not concerned with the current p/t-set. When no p/t-set
prefix is used, these commands execute in the context of the current
thread of the current process by default. That is, thread level commands
ignore the current p/t-set. Thread level commands can be applied to
multiple threads by using a prefix p/t-set. When a prefix p/t-set is used,
the commands in this section are executed in the context of each active
thread described by the prefix p/t-set. The target p/t-set is the prefix
p/t-set if present, or the current thread (not the current p/t-set) if no
prefix p/t-set exists.

The thread level commands are:

addr

ascii

assign

bin

break*

dec

decl

disasm

do

doi

dump

entry

fp

func

hex

hwatch

line

lines

lval

noprint

oct

pc

pf

print

regs

retaddr

rval

scope

set

sizeof

sp

stack

stackdump

string

track

tracki

watch

watchi

whatis

where

* breakpoints and variants (stop, stopi,
break, breaki): if no prefix p/t-set is
specified, [all] is used (overriding current p/t-set).

The following actions occur when a prefix p/t-set is used:

The threads described by the prefix are sorted per process by thread
ID in increasing order.

The processes are sorted by process ID in increasing order, and
duplicates are removed.

The command is then applied to the threads in the resulting list in
order.

Without a prefix p/t-set, the print command executes in
the context of the current thread of the current process, thread 0.0,
printing rank 0:

pgdbg [all] 0.0> print myrank
0

With a prefix p/t-set, the thread members of the prefix are sorted and
duplicates are removed. The print command iterates over
the resulting list:

The debugger supports thread and process control everywhere in the
program. Threads and processes can be advanced in groups anywhere in the
program.

The control commands are:

cont

next

step

stepout

synci

halt

nexti

stepi

sync

wait

To describe those threads to be advanced, set the current p/t-set or use a
prefix p/t-set.

A thread inherits the control operation of the current thread when it is
created. If the current thread single-steps over an
_mp_init call (found at the beginning of every OpenMP
parallel region) using the next command, then all threads
created by _mp_init step into the parallel region as
if by the next command.

A process inherits the control operation of the current process when it is
created. So if the current process returns from a call to
MPI_Init under the control of a cont
command, the new process does the same.

The debugger supports configuration of how threads and processes stop in relation to one another. The debugger defines two
pgienv environment variables, threadstop and procstop, for this purpose. The debugger defines two stop modes, synchronous (sync)
and asynchronous (async).

Table 10. Stop Modes

Command

Result

sync

Synchronous stop mode; when one thread stops at a breakpoint (event), all other threads are stopped soon after.

async

Asynchronous stop mode; each thread runs independently of the other threads. One thread stopping does not affect the behavior
of another.

Thread stop mode is set using the pgienv command as follows:

pgienv threadstop [sync|async]

Process stop mode is set using the pgienv command as follows:

pgienv procstop [sync|async]

The default is asynchronous for both thread and process stop modes. When debugging an OpenMP program, the debugger automatically
enters synchronous thread stop mode in serial regions, and asynchronous thread stop mode in parallel regions.

The pgienv environment variables threadstopconfig and procstopconfig can be set to automatic (auto) or user defined (user) to enable or disable this behavior:

pgienv threadstopconfig [auto|user]
pgienv procstopconfig [auto|user]

Selecting the user-defined stop mode prevents the debugger from changing stop modes automatically. Automatic stop configuration
is the default for both threads and processes.

Wait mode describes when the debugger will accept the next command. The wait mode is defined in terms of the execution state
of the program. Wait mode describes to the debugger which processes/threads must be stopped before it will accept the next
command.

In certain situations, it is desirable to be able to enter commands while the program is running and not stopped at an event.
The debugger prompt does not appear until all processes/threads are stopped. However, a prompt may be available before all
processes/threads have stopped. Pressing <enter> at the command line brings up a prompt if it is available. The availability
of the prompt is determined by the current wait mode and any pending wait commands.

The debugger accepts a compound statement at each prompt. Each compound statement is a sequence of semicolon-separated commands,
which are processed immediately in order.

The wait mode describes when to accept the next compound statement. The debugger supports three wait modes, which can be applied
to processes and/or threads.

Table 11. Wait Modes

Command

Result

all

The prompt is available only after all threads have stopped since the last control command.

any

The prompt is available only after at least one thread has stopped since the last control command.

none

The prompt is available immediately after a control command is issued.

Thread wait mode describes which threads the debugger will wait for before accepting new commands.

Thread wait mode is set using the pgienv command as follows:

pgienv threadwait [any|all|none]

Process wait mode describes which processes the debugger will wait for before accepting new commands.

Process wait mode is set using the pgienv command as follows:

pgienv procwait [any|all|none]

If process wait mode is set to none, then thread wait mode is ignored.

The debugger CLI defaults to:

threadwait all
procwait any

If the target program goes MPI parallel, then procwait is changed to none automatically.

If the target program goes thread parallel, then threadwait is changed to none automatically. The pgienv environment variable threadwaitconfig can be set to automatic (auto) or user defined (user) to enable or disable this behavior.

Setting the wait mode may be necessary when invoking the GUI using the -s (script file) option. This step ensures that the necessary threads are stopped before the next command is processed.

The debugger also provides a wait command that can be used to insert explicit wait points in a command stream. wait uses the target p/t-set by default, which can be set to wait for any combination of processes/threads. You can use the wait command to insert wait points between the commands of a compound command.

The pgienv variables threadwait and procwait can be used to configure the behavior of wait. For more information, refer to pgienv usage in Configurable Wait Mode.

The debugger can produce a variety of status messages during a debug session. This feature can be useful in the CLI if the
graphical aids provided by the GUI are unavailable. Use the pgienv command to enable or disable the types of status messages
produced by setting the verbose environment variable to an integer-valued bit mask:

pgienv verbose <bitmask>

The values for the bit mask, listed in the following table, control the type of status messages desired.

Table 13. Status Messages

Value

Type

Information

0x0

Standard

Disable all messages.

0x1

Standard

Report status information on current process/thread only. A message is printed when the current thread stops and when threads
and processes are created and destroyed. Standard messaging is the default and cannot be disabled.

0x2

Thread

Report status information on all threads of current processes. A message is reported each time a thread stops. If process
messaging is also enabled, then a message is reported for each thread across all processes. Otherwise, messages are reported
for threads of the current process only.

0x4

Process

Report status information on all processes. A message is reported each time a process stops. If thread messaging is also enabled,
then a message is reported for each thread across all processes. Otherwise, messages are reported for the current thread only
of each process.

0x8

SMP

Report SMP events. A message is printed when a process enters or exits a parallel region, or when the threads synchronize.
The debugger's OpenMP handler must be enabled.

This section describes how to use a p/t-set to define an event across multiple threads and processes. Events, such as breakpoints
and watchpoints, are user-defined events. User-defined events are thread-level commands, described in Thread Level Commands.

Breakpoints, by default, are set across all threads of all processes. A prefix p/t-set can be used to set breakpoints on specific
processes and threads. For example:

(i) and (ii) are equivalent. (iii) sets a breakpoint only in threads 1,2,3 of process 0.

By default, all other user events are set for the current thread only. A prefix p/t-set can be used to set user events on
specific processes and threads. For example:

i) pgdbg [all] 0> watch glob
ii) pgdbg [all] 0> [*] watch glob

(i) sets a watchpoint for glob on thread 0 only. (ii) sets a watchpoint for glob on all threads that are currently active.

When a process or thread is created, it inherits all of the breakpoints defined for the parent process or thread. All other
events must be defined explicitly after the process or thread is created. All processes must be stopped to add, enable, or
disable a user event.

Events may contain if and do clauses. For example:

pgdbg [all] 0> [*] break func if (glob!=0) do {set f = 0}

The breakpoint fires only if glob is non-zero. The do clause is executed if the breakpoint fires. The if and do clauses execute
in the context of a single thread. The conditional in the if clause and the body of the do execute in the context of a single
thread, the thread that triggered the event. The conditional definition as above can be restated as follows:

[0] if (glob!=0) {[0] set f = 0}
[1] if (glob!=0) {[1] set f = 0}
...

When thread 1 hits func, glob is evaluated in the context of thread 1. If glob evaluates to non-zero, f is bound in the context
of thread 1 and its value is set to 0.

Control commands can be used in do clauses, however they only apply to the current thread and are only well defined as the
last command in the do clause. For example:

pgdbg [all] 0> [*] break func if (glob!=0) do {set f = 0; c}

If the wait command appears in a do clause, the current thread is added to the wait set of the current process. For example:

pgdbg [all] 0> [*] break func if (glob!=0) do {set f = 0; c; wait}

If conditionals and do bodies cannot be parallelized with prefix p/t-sets. For example, the following command is illegal:

Use the wait command if subsequent commands require threads to be stopped, as the print command in the example does.

The threadwait and procwait environment variables do not affect how commands within a compound statement are processed. These pgienv environment variables describe under what conditions (state of program) the debugger should accept the next (compound) statement.

The debugger provides full control of threads in parallel regions. Commands can be applied to all threads, a single thread,
or a group of threads. The debugger uses the native thread numbering scheme for OpenMP applications to identify threads; for
other types of multi-threaded applications thread numbering is arbitrary. OpenMP private data can be accessed accurately for
each thread. The debugger provides understandable status displays regarding per-thread state and location.

Advanced features provide for configurable thread stop modes and wait modes, allowing debugger operation that is concurrent
with application execution.

The debugger automatically attaches to new threads as they are created during program execution. The debugger reports when
a new thread is created and the thread ID of the new thread is printed.

([1] New Thread)

The system ID of the freshly created thread is available through the threads command. You can use the procs command to display information about the parent process.

The debugger maintains a conceptual current thread. When using the command-line interface, the current thread is chosen by
using the thread command.

pgdbg [all] 2> thread 3
pgdbg [all] 3>

When using the GUI, the current thread can be selected using the Current Thread drop-down list or by clicking in the Thread
Grid. A subset of debugger commands known as thread-level commands apply only to the current thread. For more information,
refer to Thread Level Commands.

The threads command lists all threads currently employed by an active program. It displays each thread’s unique thread ID, system ID
(OS process ID), execution state (running, stopped, signaled, exited, or killed), signal information and reason for stopping,
and the current location if stopped or signaled. An arrow (=>) indicates the current thread. The process ID of the parent
is printed in the top left corner. The threads command does not change the current thread.

The debugger supports debugging of OpenMP private data for all supported languages. When an object is declared private in
the context of an OpenMP parallel region, it essentially means that each thread team has its own copy of the object. This
capability is shown in the following Fortran and C/C++ examples, where the loop index variable i is private by default.

FORTRAN example:

program omp_private_data
integer array(8)
call omp_set_num_threads(2)
!$OMP PARALLEL DO
do i=1,8
array(i) = i
enddo
!$OMP END PARALLEL DO
print *, array
end

The debugger is capable of debugging multi-process MPI
and hybrid multi-thread/multi-process applications. Hybrid applications
use MPI to communicate between multi-threaded or OpenMP processes. This
section begins with a general overview of how to debug parallel MPI
applications before detailing how to launch MPI applications under debug
using the various supported platforms and versions of MPI.

The debugger can debug MPI applications running on the local system and, on Linux, applications distributed across a cluster.
MPI applications must be started under debugger control. Process identification uses the MPI rank within MPI_COMM_WORLD.

MPI debugging is supported on Linux, macOS, and Windows. Application debugging is supported up to a maximum of 256 processes
and 64 threads per process, but may be limited by your PGI license keys. A PGI floating license is required to enable the
debugger's distributed debugging capabilities.

PGI has deprecated support for MPICH1, MPICH2 and MVAPICH1. For instructions on debugging an application using one of these
distributions of MPI, please refer to the documentation for release 13.10 (or prior).

In general, simply add -⁠g to the compilation and linking of an MPI application to enable the generation of debug information. Instead of invoking a
compiler directly, most versions of MPI include wrapper files (i.e., mpicc, mpif90). That said, the PGI compilers have direct support for some MPI distributions via the -⁠Mmpi option. For example, sub-options to -⁠Mmpi are available for MPICH, SGI, and MS-MPI.

In the following sections, the term launcher indicates the MPI launch program. The debugger uses mpiexec as the default launcher. If the location of the launcher in your MPI distribution is not in your PATH environment variable,
you must provide the debugger with the full path to the launcher, including the name of the launch tool itself. If the location
of the launcher is in your PATH, then you just need to provide the name of the launcher and then only if the launcher is not
mpiexec.

You can use the debugger's Connections tab to start debug sessions of programs that were built using MPICH, MS-MPI, MVAPICH2
and Open MPI. Programs built with SGI MPI can be debugged with the debugger GUI but the session must be started when the debugger
is launched.

To configure an MPI debug session, first select the MPI check box near the top of the Connections tab to enable its MPI-specific
fields. Use the Command field to specify the MPI launch program and the Arguments field to pass arguments (if any) to the
MPI launch program. The same rules discussed earlier about specifying the MPI launch program apply here as well. The examples
in the following table use eight processes and a file named ‘hosts’ to illustrate how you might go about filling in the Command
and Argument fields for different MPI distributions:

Debugging sessions for all MPI distributions supported by PGI can be started when the debugger is launched. The requirements
of the MPI distribution itself determine the command required to start the debugger. The debugger’s text and graphical modes
are both supported from a command line launch.

The launcher for MPICH v3 is mpiexec. If the path to mpiexec is not part of the PATH environment variable, then you must specify the full path to mpiexec in the pgdbg command line. If mpiexec is in your PATH, you don’t have to supply an argument to the -⁠mpi option at all because mpiexec is the default launcher name.

For example, to debug an MPICH program named cpi, which takes one program argument, using four processes, use a command like this one:

When MS-MSPI is installed, it adds the location of mpiexec to the system’s PATH environment variable so you do not need to supply an argument to the -⁠mpi option. If the path to mpiexec is not part of your PATH, then you must specify the full path to mpiexec in the pgdbg command line.

For example, to debug an MS-MPI application named prog using four processes running on the host system, use a command like this one:

The launcher for Open MPI is mpiexec. If the path to mpiexec is not part of the PATH environment variable, then you must specify the full path to mpiexec in the pgdbg command line. If mpiexec is in your PATH, you don’t have to supply an argument to the -⁠mpi option at all because mpiexec is the default launcher name.

For example, to debug an Open MPI program named cpi, which takes one program argument, using four processes, use a command like this one:

Use the debugger’s -⁠sgimpi option instead of -⁠mpi when you want to debug an SGI MPI program. Otherwise the command format for launching SGI MPI debugging is similar to that
used when debugging programs built with other distributions of MPI:

The SGI MPI launch program is mpirun. You can use -⁠sgimpi without an argument if the location of mpirun is in your PATH. If mpirun is not in your PATH, then you must specify the full path to it, including the mpirun command, as part of the -⁠sgimpi option.

When running or debugging an SGI MPI program, you need to include the SGI MPI lib directory in the LD_LIBRARY_PATH environment
variable.

For example, provided mpirun is in your PATH, to debug an SGI MPI program named fpi using four processes, use a command like:

$ pgdbg -sgimpi -np 4 fpi

When an SGI MPI debugging session starts up, a number of messages are printed to the command prompt. These messages reflect
how the debugger is setting up the session and can be safely ignored.

Program input from stdin is disabled when running an SGI MPI program using the debugger.

Here are some general things to consider when debugging an MPI program:

Use the Groups tab (p/t-sets in the CLI) to focus on a set of processes. Be mindful of process dependencies.

For a running process to receive a message, the sending process must be allowed to run.

Process synchronization points, such as MPI_Barrier, do not return until all processes have hit the sync point.

MPI_Finalize acts as an implicit barrier except when using the now deprecated MPICH1, where Process 0 returns while Processes
1 through n-1 exit.

You can apply a control command, such as cont or step, to a stopped process while other processes are running. A control command applied to a running process is applied to the
stopped threads of that process and is ignored by its running threads.

The debugger automatically switches to process wait mode none as soon as it attaches to its first MPI process. See the pgienv command and Configurable Wait Mode for details.

The debugger automatically attaches to new MPI processes as they are created by the running MPI application. The debugger
displays an informational message as it attaches to the freshly created processes.

([1] New Process)

The MPI global rank is printed with the message.

You can use the procs command to list the host and the PID of each process by rank. The current process is indicated by an arrow (=>). You can
use the proc command to change the current process by process ID.

The execution state of a process is described in terms of the execution state of its component threads. For a description
of how thread state is represented in the GUI, refer to Thread State Is Described Using Color.

The debugger command prompt displays the current process and the current thread. In the above example, the current process
was changed to process 1 by the proc 1 command and the current thread of process 1 is 0; this is written as 1.0:

Use the debugger's sync command to synchronize a set of processes to a particular point in the program. The following command runs all processes
to MPI_Finalize:

pgdbg [all] 0.0> sync MPI_Finalize

The following command runs all threads of process 0 and process 1 to MPI_Finalize:

pgdbg [all] 0.0> [0:1.*] sync MPI_Finalize

A sync command only successfully syncs the target processes if the sync address is well defined for each member of the target process
set, and all process dependencies are satisfied. If these conditions are not met, a member could wait forever for a message.
The debugger cannot predict if a text address is in the path of an executing process.

The debugger can dump MPI message queues. When using the CLI, use the mqdump command, described in Memory Access. When using the GUI, the message queues are displayed in the MPI Messages debug information tab.

The following error message may appear in the MPI Messages tab or when invoking mqdump:

If this message is displayed, then the PGDBG_MQS_LIB_OVERRIDE environment variable should be set to the absolute path of libtvmpich.so or another shared object that is compatible with the version of MPI being used. The default path can also be overridden via
the pgienv variable mqslib.

Microsoft MPI does not currently provide support for dumping message queues.

Entering Ctrl+C at the debugger's command line can be used to halt all running processes. However, this is not the preferred
method to use while debugging an MPICH1 program. (MPICH1 support has been deprecated.) The debugger automatically switches
to process wait mode none (pgienv procwait none) as soon as it attaches to its first MPI process.

Setting pgienv procwait none allows commands to be entered while there are running processes, which allows the use of the halt command to stop running processes without the use of Ctrl+C.

By default, the debugger uses rsh for
communication between remote debugger components. The debugger can also
use ssh for secure environments. The environment
variable PGRSH should be set to
ssh or rsh to indicate the
desired communication method.

If you opt to use ssh as the mechanism for launching
the debugger's remote components, you may want to do some additional
configuration. The default configuration of ssh can
result in a password prompt for each remote cluster node on which the
debugger runs. Check with your network administrator to make sure that you
comply with your local security policies when configuring
ssh.

The following steps provide one way to configure SSH to eliminate this
prompt. These instructions assume $HOME is the same
on all nodes of the cluster.

To use MPI debugging in text mode, be certain that the DISPLAY variable is undefined in the shell that is invoking mpirun.
If this variable is set, you can undefine it by using one of the following commands:

When debugging an MPI job after invoking the debugger's CLI with the -mpi option, each process is stopped before the first assembly instruction in the program. Continuing execution using step or next is not appropriate; instead, use the cont command.

The debugger supports debugging hybrid multi-thread/multi-process applications that use MPI to communicate between multi-threaded
or OpenMP processes. Multi-threaded and OpenMP applications may be run using more threads than the available number of CPUs,
and MPI applications may allocate more than one process to a cluster node. The debugger supports debugging the supported types
of applications regardless of how well the requested number of threads matches the number of CPUs or how well the requested
number of processes matches the number of cluster nodes.

The name of a thread in multilevel debug mode is the thread ID prefixed with its parent process ID. This forms a unique name
for each thread across all processes. This naming scheme is valid in all debug modes. The debugger changes automatically to
multilevel debug mode from process-only debug mode or threads-only debug mode when at least one MPI process creates multiple
threads.

Thread IDs in multilevel debug mode

0.1

Thread 1 of process 0

0.*

All threads of process 0

*

All threads of all processes

In multilevel debug, mode status and error messages are prefixed with process/thread IDs depending on context. Further, in
multilevel debug mode, the debugger displays the current p/t-set in square brackets followed by the ID of the current thread
prefixed by the ID of its parent process:

The command sections that follow use these conventions for the command names and arguments, when the command accepts one.

Command names may be abbreviated by omitting the portion of the command name enclosed in brackets ([]).

Argument names are italicized.

Argument names are chosen to indicate what kind of argument is expected.

Arguments enclosed in brackets ([]) are optional.

Two or more arguments separated by a vertical line (|) indicate that any one of the arguments is acceptable.

An ellipsis (...) indicates an arbitrarily long list of arguments.

Other punctuation, such as commas and quotes, must be entered as shown.

Syntax examples

Example 1:

lis[t] [count | lo:hi | routine | line,count]

This syntax indicates that the command list may be abbreviated to lis, and that it can be invoked without any arguments or with one of the following: an integer count, a line range, a routine name, or a line and a count.

Example 2:

att[ach] pid [exe]

This syntax indicates that the command attach may be abbreviated to att, and, when invoked, must have a process ID argument, pid. Optionally you can specify an executable file, exe.

The following commands control the execution of the target program. The debugger lets you easily group and control multiple
threads and processes. For more details, refer to Basic Process and Thread Naming.

Attach to a running process with process ID pid. Use exe to specify the absolute path of the executable file. For example, attach 1234 attempts to attach to a running process whose process ID is 1234. You may enter something like attach 1234 /home/demo/a.out to attach to a process ID 1234 called /home/demo/a.out.

The PGI debugger attempts to infer the arguments of the attached program. If the debugger fails to infer the argument list,
then the program behavior is undefined if the run or rerun command is executed on the attached process.

The stdio channel of the attached process remains at the terminal from which the program was originally invoked.

The attach command is not supported for MPI programs.

Note that on Ubuntu systems ptrace is, by default, restricted from attaching to non-child processes. As a result, the PGI debugger, as well as other debuggers
utilizing ptrace on Linux, is not able to attach to a process for debugging. There are two workarounds:

1) To temporarily allow attaching for debug, modify the file /proc/sys/kernel/yama/ptrace-scope and change the content

1

to

0

2) To permanently allow attaching for debug, modify the file /etc/sysctl.d/10-ptrace.conf and change the line

Set the current process to the process identified by id. When issued with no argument, proc lists the location of the current thread of the current process in the current program. For information on how processes
are numbered, refer to Using the CLI.

Execute the program from the beginning. If arguments arg0, arg1, and so on are specified, they are set up as the command-line arguments of the program. Otherwise, the arguments that were
used with the previous run command are used. Standard input and standard output for the target program can be redirected using < or > and an input or
output filename.

Stop after executing one source line. This command steps into called routines. The count argument stops execution after executing count source lines. The up argument stops execution after stepping out of the current routine (see stepout).

Stop after executing one instruction. This command steps into called routines. The count argument stops execution after executing count instructions. The up argument stops the execution after stepping out of the current routine (see stepout).

Stop after returning to the caller of the current subroutine. This command sets a breakpoint at the current return address
and continues execution to that point. For this command to work correctly, it must be possible to compute the value of the
return address. Some subroutines, particularly terminal (i.e. leaf) subroutines at higher optimization levels, may not set
up a stack frame. Executing stepout from such a routine causes the breakpoint to be set in the caller of the most recent routine that set up a stack frame. This
command halts execution immediately upon return to the calling subroutine.

Set the current thread to the thread identified by number; where number is a logical thread ID in the current process’ active thread list. When issued with no argument, thread lists the current program location of the currently active thread.

When no arguments
are specified, the break command prints the current
breakpoints. Otherwise, set a breakpoint at the indicated line or
routine. If a routine is specified, and the routine was compiled for
debugging, then the breakpoint is set at the start of the first statement
in the routine (after the routine’s prologue code). If the routine
was not compiled for debugging, then the breakpoint is set at the first
instruction of the routine, prior to any prologue code. This command
interprets integer constants as line numbers. To set a breakpoint at an
address, use the addr command to convert the
constant to an address, or use the breaki
command.

When a condition is specified with if, the breakpoint occurs only
when the specified condition is true. If do is specified with a
command or several commands as an argument, the command or commands are
executed when the breakpoint occurs. If hit is specified with a
number as an argument, the breakpoint occurs only when the hit count is
equal to that number. Optional operators (greater than, multiple of) can
be used to modify the hit count condition.

The following table provides examples of using break to
set breakpoints at various locations.

This break command...

Sets breakpoints...

break 37

at line 37 in the current file.

break "xyz.c"@37

at line 37 in the file
xyz.c.

break main

at the first executable line of routine main.

break {addr 0xf0400608}

at address 0xf0400608.

break {line}

at the current line.

break {pc}

at the current address.

The following command stops when routine xyz is
entered only if the argument n is greater than 10.

break xyz if(xyz@n > 10)

The next command prints the value of n and performs a
stack trace every time line 100 in the current file is reached.

break 100 do {print n; stack}

The next command stops at line 111 when the hit count is a multiple of 5.

When no
arguments are specified, the breaki command prints the
current breakpoints. Otherwise, this command sets a breakpoint at the
indicated address addr or routine.

If a routine is specified, the breakpoint is set at the first address of
the routine. This means that when the program stops at this type of
breakpoint the prologue code which sets up the stack frame will not yet
have been executed. As a result, values of stack arguments may not yet
be correct.

Integer constants are interpreted as addresses.

To specify a line, use the lines command
to convert the constant to a line number, or use the break command.

The if, do and hit arguments are interpreted in the
same way as for the break command.

The following table provides examples of setting breakpoints using
breaki.

This breaki command...

Sets breakpoints...

breaki 0xf0400608

at address 0xf0400608.

breaki {line 37}

at line 37 in the current file.

breaki "xyz.c"@37

at line 37 in the file
xyz.c.

breaki main

at the first executable address of routine main.

breaki {line}

at the current line.

breaki {pc}

at the current address.

In the following example, when n is greater than 3,
the following command stops and prints the new value of
n at address 0x6480:

When no arguments are specified, the catch command prints the list of signals being caught. With the sig:sig argument, this command catches the specified range of signals. With a list of signals, catch the signals with the specified
number(s). When signals are caught, the debugger intercepts the signal and does not deliver it to the program. The program
runs as though the signal was never sent.

Clear one or more breakpoints. Use the all argument to clear all breakpoints. Use the routine argument to clear all breakpoints from the first statement in the specified routine. Use the line number argument to clear all breakpoints from the specified line number in the current source file. Use the addr argument to clear breakpoints from the specified address addr.

When no arguments are specified, the clear command clears all breakpoints at the current location.

When no arguments are specified, the disable command prints both enabled and disabled events by event number.

With arguments, this command disables the event specified by event-number or all events. Disabling an event definition suppresses actions associated with the event, but leaves the event defined so that
it can be used later. (See the enable command.)

do {commands} [if (condition)]
do {commands} at line [if (condition)]
do {commands} in routine [if (condition)]

Define a do event. This command is similar to watch except that instead of defining an expression, it defines a list of commands to be executed. Without the optional arguments
at or in, the commands are executed at each line in the program.

Use at with a line number to specify the commands to be executed each time that line is reached. Use in with a routine to specify the commands to be executed at each line in the routine. The optional if argument has the same meaning that it has with the watch command. If a condition is specified, the do commands are executed only when the condition is true.

Define a doi event. This command is similar to watchi except that instead of defining an expression, doi defines a list of commands to be executed. If an address addr is specified, then the commands are executed each time that the specified address is reached. If a routine is specified, then the commands are executed at each instruction in the routine. If neither an address nor a routine is specified,
then the commands are executed at each instruction in the program. The optional if argument has the same meaning that it has in the do and watch commands. If a condition is specified, the doi commands are executed only when the condition is true.

Define a hardware watchpoint. This command uses hardware support to create a watchpoint for a particular address or variable.
The event is triggered by hardware when the byte at the given address is written. This command is only supported on systems
that provide the necessary hardware and software support.

Note:

Only one hardware watchpoint can be defined at a time.

When the optional if argument is specified, the event action is only triggered if the expression is true. When the optional do argument is specified, then the commands are executed when the event occurs.

Define a hardware read/write watchpoint. This event is triggered by hardware when the byte at the given address or variable
is either read or written. As with hwatch, system hardware and software support must exist for this command to be supported. The optional if and do arguments have the same meaning as for the hwatch command.

Define a hardware read watchpoint. This event is triggered by hardware when the byte at the given address or variable is read.
As with hwatch, system hardware and software support must exist for this command to be supported. The optional if and do arguments have the same meaning as for the hwatch command.

Without arguments, the ignore command prints the list of signals being ignored. With the sig:sig argument, this command ignores the specified range of signals. With a list of signals, the command ignores signals with the
specified numbers.

When a particular signal number is ignored, signals with that number sent to the program are not intercepted by the PGI debugger;
rather, the signals are delivered to the program.

Break when the value of the indicated variable var changes. Use the at argument and a line to set a breakpoint at a line number. Use the in argument and a routine name to set a breakpoint at the first statement of the specified routine. When the if argument is used, the debugger stops when the condition is true.

Break when the value of the indicated variable var changes. Set a breakpoint at the indicated address or routine. Use the at argument and an address to specify an address at which to stop. Use the in argument and a routine name to specify the first address of the specified routine at which to stop. When the if argument is used, the debugger stops when the condition is true.

Use var to activate tracing when the value of var changes. Use routine to activate tracing when the subprogram routine is called. Use at to display the specified line each time it is executed. Use in to display the current line while in the specified routine. Use inclass to display the current line while in each member function of the specified class. If a condition is specified, tracing is only enabled if the condition evaluates to true. The do argument defines a list of commands to execute at each trace point.

Use the pgienv speed command to set the time in seconds between trace points. Use the clear command to remove tracing for a line or routine.

Activate tracing at the instruction level. Use var to activate tracing when the value of var changes. Use at to display the instruction at addr each time it is executed. Use in to display memory instructions while in the subprogram routine. Use inclass to display memory instructions while in each member function of the specified class. If a condition is specified, tracing is only enabled if the condition evaluates to true. The do argument defines a list of commands to execute at each trace point.

Use the pgienv speed command to set the time in seconds between trace points. Use the clear command to remove tracing for a line or routine.

Define a watch event. The given expression is evaluated, and subsequently, each time the value of the expression changes,
the program stops and the new value of the expression is printed. If a line is specified, the expression is only evaluated at that line. If a routine is specified, the expression is evaluated at each line in the routine. If no location is specified, the expression is evaluated
at each line in the program. If a condition is specified, the expression is evaluated only when the condition is true. If commands are specified using do, they are executed whenever the expression is evaluated and its value changes.

The watched expression may contain local variables, although this is not recommended unless a routine or address is specified
to ensure that the variable is only evaluated when it is in the current scope.

Note:

Using watchpoints indiscriminately can dramatically slow program execution.

Using the at and in arguments speeds up execution by reducing the amount of single-stepping and expression evaluation that must be performed
to watch the expression. For example:

Define an assembly-level watch event. This command functions similarly to the watch command with two exceptions: 1) the argument interprets integers as addresses rather than line numbers and 2) the expression is evaluated at every instruction rather than at every line.

This command is useful when line number information is limited, which may occur when debug information is not available or
assembly must be debugged. Using watchi causes programs to execute more slowly than watch.

when do {commands} [if (condition)]
when at line do {commands} [if (condition)]
when in routine do {commands} [if (condition)]

Execute commands at every line in the program, at a specified line in the program, or in the specified routine. If an optional condition is specified, commands are executed only when the condition evaluates to true.

Execute commands at each address in the program. If an address addr is specified, the commands are executed each time the address is reached. If a routine is specified, the commands are executed at each line in the routine. If an optional condition is specified, commands are executed whenever the condition evaluates to true.

If no argument is given, disassemble four instructions starting at the current address. If an integer count is given, disassemble count instructions starting at the current address. If an address range (lo:hi) is given, disassemble the memory in the range. If a routine is given, disassemble the entire routine. If the routine was compiled for debugging and source code is available, the source
code is interleaved with the disassembly. If an address addr and a count are both given, disassemble count instructions starting at the provided address.

Use the editor specified by the environment variable $EDITOR to edit a file.

If no argument is supplied, edit the current file starting at the current location. To edit a specific file, provide the filename argument. To edit the file containing the subprogram routine, specify the routine name.

By default, list displays ten lines of source centered at the current source line. If a count is given, list the specified number of lines. If a line and count are both given, start the listing of count lines at line. If a line range (lo:hi) is given, list the indicated source lines in the current source file. If a routine name is given, list the source code for the indicated routine. If a number is specified with routine, list the first number lines of the source code for the indicated routine.

list [dbx mode]

The list command works somewhat differently when the debugger is in dbx mode.

lis[t] [ line | first,last | routine | file ]

By default, list displays ten lines of source centered at the current source line. If a line is provided, the source at that line is displayed. If a range of line numbers is provided (first,last), lines from the first specified line to the last specified line are displayed. If a routine is provided, the display listing begins in that routine. If a file name is provided, the display listing begins in that file. File names must be quoted.

Print the call stack. This command displays a hex dump of the stack frame for each active routine. This command is an assembly-level
version of the stacktrace command. If a count is specified, display a maximum of count stack frames.

Print the call stack. Print the available information for each active routine, including the routine name, source file, line
number, and current address. This command also prints the names and values of any arguments, when available. If a count is specified, display a maximum of count stack frames. The stacktrace and where commands are equivalent.

Print the call stack. Print the available information for each active routine, including the routine name, source file, line
number, and current address. This command also prints the names and values of any arguments, when available. If a count is specified, display a maximum of count stack frames. The where and stacktrace commands are equivalent.

This section describes the PGI debugger commands used for printing and setting variables. The primary print commands are print and printf, described at the beginning of this section. The rest of the commands for printing provide alternate methods for printing.

Evaluate and print
one or more expressions. This command is invoked to print the result of
each line of command input. Values are printed in a format appropriate to
their type. For values of structure type, each field name and value is
printed. Character pointers are printed as a hex address followed by the
character string.

Character string constants print out literally using a comma-separated
list. For example:

pgdbg> print "The value of i is ", i

Prints this:

"The value of i is", 37

The array sub-range operator (:) prints a range of an array. The following
examples print elements 0 through 9 of the array a:

C/ C++[ example 1:

pgdbg> print a[0:9]
a[0:4]: 0 1 2 3 4
a[5:9]: 5 6 7 8 9

FORTRAN example 1:

pgdbg> print a(0:9)
a(0:4): 0 1 2 3 4
a(5:9): 5 6 7 8 9

Notice that the output is formatted and annotated with index
information. The debugger formats array output into columns. For each row,
the first column prints an index expression which summarizes the elements
printed in that row. Elements associated with each index expression are
then printed in order. This is especially useful when printing slices of
large multidimensional arrays.

The debugger also supports array expression strides. Below are examples
for C/ C++ and FORTRAN.

C/ C++ example 2:

pgdbg> print a[0:9:2]
a[0:8]: 0 2 4 6 8

FORTRAN example 2:

pgdbg> print a(0:9:2)
a(0:8): 0 2 4 6 8

The print statement may be used to display members of derived types in
FORTRAN or structures in C/ C++. Here are examples.

Print expressions in the format indicated by the format string. This command behaves like the C library function printf. For
example:

pgdbg> printf "f[%d]=%G",i,f[i]
f[3]=3.14

The pgienv stringlen command sets the maximum number of characters that print with a print command. For example, the char declaration below:

char *c="a whole bunch of chars over 1000 chars long....";

By default, the print c command prints only the first 512 (default value of stringlen) bytes. Printing of C strings is usually terminated by the
terminating null character. This limit is a safeguard against unterminated C strings.

Evaluate and print exp as an ASCII character. Control characters
are prefixed with the '^' character; for example, 3 prints as
^c. Otherwise, values that cannot be printed as characters are printed as
integer values prefixed by ‘\’. For example, 250 is printed
as \250.

Set variable var to the value of the expression exp. The variable can be any valid identifier accessed properly for the current scope. For example, given a C variable declared
‘int * i’, you can use the following command to assign the value 9999 to it.

Call the named routine. C argument passing conventions are used. Breakpoints encountered during execution of the routine are ignored. Fortran functions
and subroutines can be called, but the argument values are passed according to C conventions. The debugger may not always
be able to access the return value of a Fortran function if the return value is an array. In the example below, the debugger
calls the routine foo with four arguments:

pgdbg> call foo(1,2,3,4)

If a signal is caught during execution of the called routine, the debugger stops the execution and asks if you want to cancel
the call command. For example, suppose a command is issued to call foo as shown above, and for some reason a signal is sent to the process while it is executing the call to foo. In this case, the debugger prints the following prompt:

PGDBG Message: Thread [0] was signalled while executing a function
reachable from the most recent PGDBG command line call to foo. Would you
like to cancel this command line call? Answering yes will revert the register
state of Thread [0] back to the state it had prior to the last call to foo
from the command line. Answering no will leave Thread [0] stopped in the call
to foo from the command line.
Please enter 'y' or 'n' > y
Command line call to foo cancelled

Answering yes to this question returns the register state of each thread back to the state they had before invoking the call command. Answering no to this question leaves each thread at the point they were at when the signal occurred.

Note:

Answering no to this question and continuing execution of the called routine may produce unpredictable results.

Print the declaration for the symbol name based on its type according to the symbol table. The symbol must be a variable,
argument, enumeration constant, routine, structure, union, enum, or typedef tag.

Return the lvalue of the expression expr. The lvalue of an expression is the value it would have if it appeared on the left hand side of an assignment statement.
Roughly speaking, an lvalue is a location to which a value can be assigned. This may be an address, a stack offset, or a register.

Return the rvalue of the expression expr. The rvalue of an expression is the value it would have if it appeared on the right hand side of an assignment statement.
The type of the expression may be any scalar, pointer, structure, or function type.

Set variable var to the value of expression. The variable can be any valid identifier accessed properly for the current scope. For example, given a C variable declared
int * i, the following command could be used to assign the value 9999 to it.

Return a symbol for the search scope. The search scope is set to the current routine each time program execution stops. It
may also be set using the enter command. The search scope is always searched first for symbols.

Print the names and values of registers. By default, regs prints the General Purpose registers. Use the -⁠grp option to specify one or more register groups, the -⁠fmt option to specify one or more display formats, and -⁠mode to specify scalar or vector mode. Use the -⁠info option to display the register groups on the current system and the display formats available for each group. All optional
arguments with the exception of -⁠info can be used with the others.

This command dumps the contents of a region of memory. The output is formatted according to a descriptor. Starting at the
indicated address, values are fetched from memory and displayed according to the format descriptor. This process is repeated
count times.

Interpretation of the format descriptor is similar to that used by printf. Format specifiers are preceded by %.

The recognized format descriptors are for decimal, octal, hex, or unsigned:

%d, %D, %o, %O, %x, %X, %u, %U

Default size is machine dependent. The size of the item read can be modified by either inserting 'h' or 'l' before the format
character to indicate half word or long word. For example, if your machine’s default size is 32-bit, then %hd represents a
16-bit quantity. Alternatively, a 1, 2, or 4 after the format character can be used to specify the number of bytes to read.

Return a routine symbol. If no argument is specified, return the current routine. If an address is given, return the routine
containing addr. An integer argument is interpreted as an address. If a line is specified, return the routine containing that line.

Create a source line conversion. If no argument is given, return the current source line. If an integer n is given, return it as a line number. If a routine is given, return the first line of the routine. If an address is given, return the line containing that address.

For example, the following command returns the line number of the specified address:

Without arguments, connect prints the current connection and the list of possible connection targets. Use -t to connect to a specific target. Use -d to connect to a target specified by path. Use -f to print a list of possible targets as contained in a file, or to connect to a target selected by name from the list defined in file. Pass configuration arguments to the target as appropriate.

If no argument is specified, the currently defined directories are printed. This command assists in finding source code that
may have been moved or is otherwise not found by the PGI debugger's default search mechanisms.

For example, the following statement adds the directory morestuff to the list of directories to be searched.

dir morestuff

Now, source files stored in morestuff are accessible to the debugger.

If the first character in pathname is ~, then $HOME replaces that character.

Digest symbolic debug information from each shared library at load time

pgienv mode serial

Single thread of execution (implicit use of p/t-sets)

pgienv mode thread

Debug multiple threads (condensed p/t-set syntax)

pgienv mode process

Debug multiple processes (condensed p/t-set syntax)

pgienv mode multilevel

Debug multiple processes and multiple threads

pgienv omp [on|off]

Enable/Disable the PGI debugger's OpenMP event handler. This
option is disabled by default. The OpenMP event handler, when
enabled, sets breakpoints at the beginning and end of each
parallel region. Breakpoints are also set at each thread
synchronization point. The handler coordinates threads across
parallel constructs to maintain source level debugging. This
option, when enabled, may significantly slow down program
performance. Enabling this option is recommended for localized
debugging of a particular parallel region only.

pgienv prompt <name>

Set the command-line prompt to <name>

pgienv promptlen <num>

Set maximum size of p/t-set portion of prompt

pgienv speed <secs>

Set the time in seconds <secs> between trace points

pgienv stringlen <num>

Set the maximum # of chars printed for ‘`char *'s’

pgienv termwidth <num>

Set the character width of the display terminal.

pgienv logfile <name>

Close logfile (if any) and open new logfile <name>

pgienv threadstop sync

When one thread stops, the rest are halted in place

pgienv threadstop async

Threads stop independently (asynchronously)

pgienv procstop sync

When one process stops, the rest are halted in place

pgienv procstop async

Processes stop independently (asynchronously)

pgienv threadstopconfig auto

For each process, debugger sets thread stopping mode to 'sync' in serial regions, and 'async' in parallel regions

pgienv threadstopconfig user

Thread stopping mode is user defined and remains unchanged by the debugger.

pgienv procstopconfig auto

Not currently used.

pgienv procstopconfig user

Process stop mode is user defined and remains unchanged by the debugger.

pgienv threadwait none

Prompt available immediately; do not wait for running threads

pgienv threadwait any

Prompt available when at least one thread stops

pgienv threadwait all

Prompt available only after all threads have stopped

pgienv procwait none

Prompt available immediately; do not wait for running processes

pgienv procwait any

Prompt available when at least a single process stops

pgienv procwait all

Prompt available only after all processes have stopped

pgienv threadwaitconfig auto

For each process, the debugger sets the thread wait mode to
‘all’ in serial regions and ‘none’ in
parallel regions. (default)

pgienv threadwaitconfig user

The thread wait mode is user-defined and remains unchanged by the debugger.

pgienv mqslib default

Set MPI message queue debug library by inspecting executable.

pgienv mqslib <path>

Determine MPI message queue debug library to <path>.

pgienv verbose <bitmask>

Choose which debug status messages to report. Accepts an integer valued bit mask of the following values:

Repeat the execution of one or more previous history list commands. Use the num argument to re-execute the last num commands. With the first and last arguments, re-execute commands number first to last (optionally n times).

Fork a shell and give it the indicated arguments. The default shell type is sh or defined by $SHELL. If no arguments are specified,
an interactive shell is invoked, and executes until a Ctrl+D is entered.

The PGI User
Forum is monitored
by members of the PGI engineering and support teams as well as other
PGI customers. The forums contain answers to many commonly asked questions.
Log in
to the PGI website to access the forums.

Notice

ALL NVIDIA DESIGN SPECIFICATIONS, REFERENCE BOARDS, FILES, DRAWINGS, DIAGNOSTICS, LISTS, AND OTHER DOCUMENTS (TOGETHER AND
SEPARATELY, "MATERIALS") ARE BEING PROVIDED "AS IS." NVIDIA MAKES NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE
WITH RESPECT TO THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTABILITY, AND FITNESS
FOR A PARTICULAR PURPOSE.

Information furnished is believed to be accurate and reliable. However, NVIDIA Corporation assumes no responsibility for the
consequences of use of such information or for any infringement of patents or other rights of third parties that may result
from its use. No license is granted by implication of otherwise under any patent rights of NVIDIA Corporation. Specifications
mentioned in this publication are subject to change without notice. This publication supersedes and replaces all other information
previously supplied. NVIDIA Corporation products are not authorized as critical components in life support devices or systems
without express written approval of NVIDIA Corporation.

Trademarks

NVIDIA, the NVIDIA logo, Cluster Development Kit, PGC++, PGCC, PGDBG, PGF77, PGF90, PGF95, PGFORTRAN, PGHPF, PGI, PGI Accelerator,
PGI CDK, PGI Server, PGI Unified Binary, PGI Visual Fortran, PGI Workstation, PGPROF, PGROUP, PVF, and The Portland Group
are trademarks and/or registered trademarks of NVIDIA Corporation in the U.S. and other countries. Other company and product
names may be trademarks of the respective companies with which they are associated.