Picture this scenario: Your critical CICS region has been running for three weeks, processing millions of transactions. Suddenly, a specific transaction path starts behaving erratically. Traditional debugging would require bringing down the region, adding debugging hooks, and restarting. That means potentially hours of downtime and lost state information. Cross-memory debugging with z/XDC eliminates this disruption entirely, allowing you to hook into running programs, set breakpoints, and trace execution without any restarts.
The Power of Live System Debugging
Cross-memory debugging represents a fundamental shift in how we approach problem diagnosis on z/OS. Instead of reproducing issues in test environments or adding diagnostic code and waiting for problems to recur, you connect directly to running address spaces and insert debugging logic on the fly. This capability becomes essential for intermittent problems that resist reproduction, performance issues that only manifest under production loads, and critical systems where any downtime carries significant business impact.
The technique works by leveraging z/OS’s cross-memory services to establish debugging hooks in target address spaces. Once established, these hooks trigger debugging sessions when execution reaches your specified points, all while the rest of the application continues running normally. You gain surgical precision in debugging without the sledgehammer approach of system-wide traces or restarts.
Starting Your Cross-Memory Debugging Session
Begin with what we call a dummy XDC session. This minimal debugging environment serves as your launching pad for cross-memory operations. Start it using TSO command XDCCALLA IEFBR14. This creates an authorized debugging session running essentially nothing, giving you a clean environment to work from.
The XDCCALLA authorization is crucial here. Cross-memory debugging requires supervisor state authority to manipulate storage and control blocks in other address spaces. IEFBR14 serves as a placeholder program that immediately exits, leaving you in the XDC environment ready to target other address spaces.
From this dummy session, the entire system becomes accessible. You can examine any address space your security authorizations permit, set hooks in running code, and establish debugging sessions that activate when specific conditions occur.
Targeting Your Address Space
Once in your dummy session, use the SET ASID command to target your desired address space. You can specify the ASID numerically or use the job name for easier identification. For example, SET ASID CICSPROD targets your production CICS region, while SET ASID 0042 targets ASID 66 in hexadecimal.
After setting your target ASID, XDC’s commands operate within that address space’s context. Memory displays show the target’s storage, module maps reflect its loaded programs, and hooks you set apply to its execution stream. This context switch happens transparently. You work as if you were debugging locally while XDC handles the cross-memory mechanics behind the scenes.
Verify your target selection with the DISPLAY ASID command, which confirms the current address space context and shows key information about the target environment. This verification step prevents accidentally setting hooks in the wrong address space, a mistake that could have significant consequences in production environments.
Setting Hooks in Running Code
With your target address space selected, map the modules you want to debug using the MAP command. If the module resides in PLPA or LINKLIST, it’s already accessible. For private modules, ensure you have appropriate access to the target address space’s storage.
Setting a hook follows familiar debugging patterns. Use BREAK to establish breakpoints at specific addresses or labels. Use TRACE to track execution flow through routines. The difference lies in when these debugging directives activate. Instead of immediately affecting execution, they wait dormantly until the target code executes.
For example, to debug a problematic PC routine:
MAP PCROUTER
BREAK PCROUTER+X’200′
When execution reaches that offset in PCROUTER, z/XDC automatically creates a new debugging session. You’ll receive notification and can connect to debug the specific instance while other instances of the same code continue running normally.
Working with System Components
Cross-memory debugging excels at examining system-level code that traditional debugging cannot touch. SVC routines, for instance, run in supervisor state across multiple address spaces. With cross-memory hooks, you can trace SVC execution, examine parameter passing, and understand exactly how your applications interact with z/OS services.
System exits present another perfect use case. These routines run in privileged states at critical system junctures. Setting cross-memory hooks allows you to debug exit behavior without modifying the exit code itself. This becomes particularly useful when diagnosing problems with vendor-supplied exits where you lack source code access.
PC routines, the backbone of cross-memory services in z/OS, become fully debuggable. You can trace space-switch PC routines as they move between address spaces, examine stacking PC behavior, and understand the complex interactions between authorized services and their callers.
Managing PLPA and LINKLIST Modules
Modules in PLPA (Pageable Link Pack Area) and LINKLIST represent shared code used across the system. Debugging these modules traditionally requires IPLs to install modified versions with debugging hooks. Cross-memory debugging eliminates this requirement entirely.
To debug a PLPA module, map it within your debugging session and set hooks as needed. These hooks apply only to execution paths that encounter them. Other users of the same module remain unaffected. This isolation allows surgical debugging of shared system components without system-wide impact.
For LINKLIST modules, the process remains identical. Whether debugging IBM-supplied modules to understand behavior or your own LINKLIST-resident code, cross-memory hooks provide immediate access without the overhead of creating special debugging versions or scheduling IPL windows.
Advanced Hook Management
Conditional hooks add precision to your debugging. Instead of breaking on every execution, establish conditions that trigger only for specific scenarios. For instance, hook a routine only when called from a particular program, when certain register values appear, or when specific data conditions exist.
Set up multiple hook points to trace complex execution paths. As your target program moves through different routines and modules, your hooks create a breadcrumb trail of debugging sessions. Each session captures the state at that moment, allowing you to piece together the complete execution story.
Remove hooks cleanly when debugging completes. The CLEAR command removes specific breakpoints, while RESET clears all hooks in the current context. This cleanup ensures your debugging doesn’t leave residual effects on the production system.
Real-World Debugging Scenarios
Consider debugging a storage leak in a long-running started task. Traditional approaches might involve adding storage tracking code, restarting the task, and waiting days for the leak to manifest. With cross-memory debugging, you hook the storage management routines immediately, tracking allocations and frees in real-time without disturbing the task’s operation.
For performance problems, cross-memory hooks provide precise timing information. Set hooks at routine entry and exit points to measure execution time. Since you’re debugging the actual production workload, your measurements reflect true system behavior rather than test environment approximations.
Intermittent abends that occur rarely but cause significant disruption become manageable. Set hooks in error handling paths or at points where the abend might originate. Leave these hooks dormant for days or weeks if necessary. When the problem finally occurs, you have immediate access to the exact state that caused the failure.
Safety Considerations and Best Practices
Cross-memory debugging wields significant power, demanding corresponding responsibility. Always verify your target address space before setting hooks. A misplaced hook in a critical system component could trigger unintended debugging sessions or, worse, disrupt system operation.
Test your debugging approach in development environments when possible. While cross-memory debugging safely handles most scenarios, understanding your specific debugging sequence in a controlled environment reduces production risks.
Coordinate with operations and system programming teams. Let them know you’re conducting cross-memory debugging, which address spaces you’re targeting, and what behavior they might observe. This communication prevents confusion if debugging sessions appear in system logs or monitoring tools.
Monitor the performance impact of your hooks. While individual hooks add minimal overhead, numerous hooks in frequently executed paths can accumulate noticeable performance degradation. Remove unnecessary hooks promptly and use conditional hooks to minimize activation frequency.
Document your debugging session thoroughly. Record which hooks you set, what conditions you observed, and how you resolved issues. This documentation becomes essential when similar problems arise or when other team members need to understand your debugging approach.
Mastering Live System Diagnosis
Cross-memory debugging changes z/OS problem diagnosis from a disruptive necessity into a surgical precision tool. By hooking into running programs without restarts, you maintain system availability while gaining deep insights into program behavior. Whether debugging system exits, tracing PC routines, or diagnosing problems in PLPA modules, cross-memory debugging provides capabilities that traditional debugging cannot match.
The technique requires practice and careful application, but the payoff in reduced downtime and faster problem resolution justifies the investment. Start with simple scenarios in development, gradually building your expertise until cross-memory debugging becomes a natural part of your debugging toolkit. When that critical production issue arises, you’ll have the skills and confidence to diagnose and resolve it without the disruption of a restart.