Introduction

Unfortunately the z/TPF debugger, Performance Analyzer, Code Coverage Tool and so on cannot find and solve your code bugs. However, the z/TPF debugger and associated tools can help you locate and identify your code bugs. The key is to understand what features are available and to creatively use them together to diagnose your code bugs. How do you learn about the features of the debugger and associated tools?

  • Documentation is available at See the Fast links section on the lower left side for the following information:
  • TPFUG presentations – A debugger and TPF Toolkit update is often provided at each TPFUG to announce new features, provide education and so on. These presentations are usually given in the TPF Toolkit Task Force or the Development Tools Subcommittee.
  • Tools-z/TPF Debugger ->Debugger for z/TPF Demo Movie – This demo movie was created several years ago to highlight the function that was available at that time. Even though this movie is out of date, the education delivered in this format has been found to be very useful and the core function described continues to exist today.
  • TPF Family Libraries -> OpenCurrentInformationCenter -> z/TPF PUT -> Library -> Debugger User’s Guide – The Debugger User's Guide describes the essence of using the debugger and is a good source for what function is currently available.
  • Tools -> z/TPF Debugger ->z/TPF Redbook - z/TPF Application Modernization using Standard and Open Middleware Redbook. See appendices A-D for an in depth step by step discussion for using the TPF Toolkit, Debugger, Code Coverage Tool, and so on. This may be a good resource if you are new to the toolset.
  • Tools-z/TPF Debugger - The practical education articles, of which this article is part, provide explanations of how to use various debugger features to address debugging situations.
  • Tools-z/TPF Debugger - The developerworks Custom Communications Packages article provides an explanation of how to administer customer communication packages to address debugging situations.
  • The TPF Toolkit help that is found in the Help menu also provides information regarding the features that are available. Select the Help menu -> Help contents. Then select Debugging TPF Applications, Analyzing Code Coverage of TPF Applications, or Analyzing Performance of TPF Applications.
  • This set of documentation.
  • Experimentation – Experimenting with the tool is one of the best ways to understand how the tool works.
  • Ask IBM – You can open a PMR to ask your question or send an email to with your question. If your question is involved enough or you have a large number of questions, ask to have conference call with the experts to get your questions answered.

The purpose of this documentation is to augment the information currently available in the Debugger User's Guide and TPF Toolkit help documents by describing the ways in which the debugger and associated tools can be used to solve problems. The approach of this documentation is to examine different situations and come up with ideas about how to use different features of the debugger to diagnose the problem.

Revision / Date / Description
0 / Initial Publication
1 / 11/11/2014 / TPF Registration Entry monitor

How do I register the debugger?

The first question you may be asking is why do I need to register the debugger? The z/TPF debugger is a remote debugger in that the debugger GUI (the TPF Toolkit) resides on your workstation while the application and debugger backend reside on the server. As such, the server (z/TPF in particular) needs to be told you want to debug your application.

The key to registering the debugger to debug your application is to understand your application. For example, it is ideal to know the answer to questions such as:

How is my entry control block (ECB) started? Is this ECB started by a CREMC, CRETC, TPF_fork, SWISC CREATE or so on? Is this ECB started by a pthread_create? Or is this ECB started from a communications terminal such as an incoming message on a line number, interchange address, and terminal address (LNIATA), internet protocol (IP) or logical unit (LU).

How does my application behave? Does it create ECBs such as CREMC or so on? Does it create threads? Are there events, lockcs, signals, waiting for user input (ZPAGE), waiting for responses from another system, or so on?

What part of my application do I need to debug? Does it call global constructors? Is a library malfunctioning or is the mainline path? Is a system function or macro not returning the expected result?

Where is the right spot in my application to start debugging so that you are close to the cause of the problem?

Maybe you don't know your application in this level of detail. Do you know a main entry point name, a library used, or so on?

The more you understand your application, the more effectively you will be able to register the debugger to debug the ECB you need to debug. Notice the language used in this introduction is centered on debugging an ECB or ECBs. Many tools such as ZSPER are program centric debugging tools, which means that the code trapped on is what is debugged regardless of which ECB executes that code.The z/TPF debugger is an ECB centric debugger which means that the ECB is debugged regardless of which code that ECB executes. This is an important distinction and may be a change in mindset to how you are used to debugging. As you think about starting the z/TPF debugger, always be thinking in terms of catching the right ECB that will execute the code you need to debug.

How do you determine the right ECB to debug?

If you are intimately familiar with your application, this probably won't be a question you're asking. But if you don't know your application, you need some way to familiarize yourself with you application and the debugger tools can help you. The Determining code path article discusses how to use the trace log, code coverage, and debugger tools to learn about the path of your code. For example, in the code coverage tool, you can use the wild card (*) to register modules such as j* (assuming your application package begins with j). Drive your application and see which modules (objects and functions too) are executed in the code coverage results. Or refer to the Problem Diagnosis article to learn how to beginning debugging when you have a reproducible dump.

Know what debugger tools are available and how they work

The second key to starting the debugger effectively is knowing what features the debugger has, how to use them, and what the limitations are. The balance of this article will take the approach of example oriented explanations of the registration features that are available. The z/TPF debugger has a wide range of registration options including:

  • Register by program name
  • Register by function name
  • Register by SVC
  • Register by system error
  • Register by CTEST
  • Register by user defined registration

We will also discuss the registration options and features:

  • TPF terminal
  • Conditional registration
  • Trace created entries
  • Trace global variable initialization
  • Debugging threaded applications
  • Tips for registering on shared test systems
  • Other registration tips

Register by program name

In the z/TPF environment, the traditional linkage is termed Enter/Back which refers to the use of the z/TPF macros ENTxC and BACKC. A dictate of this linkage and the structure of the z/TPF environment is that all programs (or modules in the debugger) must have a 4-character name. Over the generations of TPF, additional forms of linkage have evolved including C/C++ function calls, main entry points, TMSPC, PRLGC, libraries and so on. But the dictate that all modules (basic assembler language (BAL) shared objects (BSOs) and C shared objects (CSOs)) must be built with a 4-character name remains.

The register by program name feature takes advantage of this 4-character program naming dictate. When using register by program name, you specify the 4-character program name you want to debug. The first ECB that enters that program by nearly any linkage type will start the debugger. The exceptions are the system special linkage libraries such as CTAL, DATA modules or the TPFDF programs that use fast linkage, these modules cannot start the debugger. That first ECB claims the registration entry and any other ECB on the system can enter that program without interference from the debugger. The debugged ECB is put to sleep while the debugger awaits instructions from you and the system continues to run in the background.

The register by program name feature does support wild cards though at least the first character of the program name must be specified such as q*. The TPF terminal and conditional registration features function as filters as to which ECBs are candidates for starting the debugger when the registered program is entered (see TPF terminal and Conditional registration below).

You can specify multiple program names. Each program name specified is indicating a possible starting location for the debugger. This may be useful if you don't know which path the application ECB may take. This list of program names has no effect upon how a debugger session will behave once it is started (for example the list of program names registered will not limit which programs the debugger will allow you to debug during the life of your ECB). This list only affects when the debugger will start.

To create a debugger session for a known entry point of your application, do the following:

Start the TPF Toolkit, switch to the Remote System Explorer Perspective, and switch to the Remote Systems view. Expand your TPF connection, right click on the Debugger Subsystem and choose new-> New Session. Choose the Program registration type and add the program names to the list.

Figure : Register by program name

Lastly, start your application. When your application enters a program name that you have registered, the debugger will start.

The following is a quick introduction to the primary views of the z/TPF debugger:

The Debug view shows the current stack frame and allows you to perform related actions. The editor view shows your source file or disassembled code and allows you to monitor expressions, perform execute actions, create breakpoints and so on. The ECB Summary view is a z/TPF specific view that shows a variety of detail regarding the ECB being debugged. The variables view shows the local variables for the currently selected stack frame in the debug view. The breakpoints view allows you to set a variety of breakpoints. The modules view shows the modules the debugger currently has loaded information for and allows you to explore source and set breakpoints. The monitors view allows you to evaluate specific expressions that you enter. The memory view allows you to explore the contents of memory. The debug console allows you to issue commands directly to the debugger engine (issue help for the list of available commands). The debugger also provides a host of views of z/TPF specific data including the ECB, data levels, DECB, DETAC, ALASC, SW00SR (TPFDF), TPF Malloc, and Record Hold views. Use these features in conjunction with each other to explore the state and operation of your ECB to debug your application code.

Figure : z/TPF debugger

Register by function name

Suppose you have used trace log, ECB trace, code coverage, or the debugger to understand the path your application takes and discovered that a particular function is returning an incorrect value. Or suppose based on the output of your application, you know a particular function is not returning the correct value. You can register the debugger to start when an ECB enters that function.

To create a debugger session for a known function entry point of your application, do the following:

Start the TPF Toolkit, switch to the Remote System Explorer Perspective, and switch to the Remote Systems view. Expand your TPF connection, right click on the Debugger Subsystem and choose new-> New Session. Choose the Function registration type and specify the function name, module name and so on.

Function names can be specified as mangled names (compiler produced names as seen in listing, ZDMAP and so on). This is useful for debugging a particular overloaded C++ function. Suppose we have two member functions in the class IVALinkedList named erase.

int erase(IVALLElement *pos);

int erase(IVAValue value, TestAgainstElement *func);

If you register the function name erase, the debugger will start when either of these functions is called as well as any other function named erase defined outside of this class. In order to only start the debugger when the second version of erase above is called, register the compiler generated mangled named:

_ZN13IVALinkedList5eraseE8IVAValuePFP12IVALLElementRS0_S2_E

An alternative way to specify the erase function is to include the class and namespace name by use the :: operator, such as IVALinkedList::erase from our example here or MyNamespace::IVALinkedList::erase

Function names can be specified as demangled names such as dispHelp. Specify the function name just as you coded it without including parenthesis or parameters

Function names can be specified to include wildcards such as disp*. You can also specify wild cards for the namespace, class or function names such as I*::e*

Function names registered are always case sensitive.

The Module Name can also contain a wildcard (*). However, a CTL-10 is possible. It is highly recommend that you specify the module name because this will also reduce any performance impacts on the system.

Click OK and then register your session.

Figure : Function registration entry

Lastly, start your application. When your application enters the function name that you have registered, the debugger will start. That first ECB claims the registration entry and any other ECB on the system can enter that function without interference from the debugger. The debugger views and so on will function as described in register by program name.

Register by SVC

Suppose you have used trace log, ECB trace, code coverage, or the debugger to understand the path your application takes and discovered that a particular SVC macro is returning an incorrect value. Or suppose based on the output of your application, you know a particular SVC macro is not returning the correct value. You can register the debugger to start when an ECB issues an SVC macro of that type.

To create a debugger session for an SVC macro of your application, do the following:

Start the TPF Toolkit, switch to the Remote System Explorer Perspective, and switch to the Remote Systems view. Expand your TPF connection, right click on the Debugger Subsystem and choose new-> New Session. Choose the SVC macro registration type and specify the SVC macro name, module name and so on.

The SVC macro name cannot be a macro group name.

The program names can include wild card characters.

Click OK and then register your session.

Figure : SVC macro registration entry

Lastly, start your application. When your application issues the registered SVC macro (the first issuing of the macro) in the programs that you have registered, the debugger will start. That first ECB claims the registration entry and any other ECB on the system can enter that function without interference from the debugger. The debugger views and so on will function as described in register by program name.

Register by system error

Register by system error name starts the debugger when the specified system error occurs and starts the debugger on the application at the location just prior to the location of the dump (as if the dump has not occurred yet). Register by system error is discussed in the Problem Diagnosis article. See that articlefor more information.

Figure : System error registration entry

Register by CTEST

Suppose you want to start the debugger at a specific location in your application and you are able to make and load a code change. You can code a call to the CTEST function in your application as ctest(NULL). The CTEST function is a user defined registration type (described in the next topic). However, calls to the CTEST function will also act as an unmodifiable breakpoint. Register by CTEST will start a debugger session when the CTEST function is called by any application.

When registering by CTEST, there are no parameters to register. If multiple people register for CTEST on a system, the registration entry behaves in a first come first served fashion. For example, suppose user A registers for CTEST, then user B registers for CTEST, and then user B starts the application with a CTEST function call coded. A debugger session will start for the application of user B on the registration entryand TPF Toolkit instance of user Abecause the registration entry of user A came first. As a result of this behavior, this function may not behave in a predictable fashion on shared test systems and it is not advisable to leave calls to the CTEST function in your application. However, the user defined registration can be used to overcome this shortcoming. The advantage of using register by CTEST over register by user defined is that CTEST is quick and easy to use while register by user defined is more involved to set up.