__le_traceback() — Call chain traceback service

Standards

Standards / Extensions C or C++ Dependencies

Language Environment

both

z/OS® V1.9

AMODE 64

Format

#include <__le_api.h>

void  __le_traceback(int cmd, void* cmd_parms, _FEEDBACK *fc);

General description

The __le_traceback() function assists in tracing the call chain. It identifies the language, program unit, entry point, current location, caller's DSA, and other information from the address of a DSA for a program unit. This is essential for creating meaningful traceback messages.
Parameter
Description
cmd
The __le_traceback() command to be used. The following commands can be used:
__TRACEBACK_FIELDS
Information that can be used to create a traceback message is returned in individual fields.
cmd_parms
A pointer to a structure that contains additional command specific parameters. For the command __TRACEBACK_FIELDS, this parameter must point to a __tf_parms_t.
fc
A 16-byte feedback code indicating the results of this function.
Table 1. Feedback Codes for __le_traceback()
Code Severity Message number Message text
CEE000 0 - - The service completed successfully.
CEE310 3 3104S Information could not be successfully extracted for this DSA. It is likely that the dsaptr parameter does not point to an actual DSA or save area.
CEE316 2 3110E The cmd parameter is not a valid command for __le_traceback().
CEE3NS 1 3836W A statement number is not available for this DSA. DWARF data in the load module is corrupted.
CEE3NT 1 3837W Statement numbers are not available. The explicit DLL load of DLL CDAEQED failed with feedback code fc.
CEE3NU 1 3838W Statement numbers are not available. The explicit DLL load of DLL CDAEQDPI failed with feedback code fc.
CEE3NV 1 3839W Statement numbers are not available. The explicit DLL load of DLL CELQDSNF failed with feedback code fc.
CEE3O0 1 3840 Statement numbers are not available. dllqueryfn() failed for a function in the DLL CELQDSNF.
CEE3O1 1 3841 A statement number is not available for this DSA. An internal routine failed with return code return-code and reason code reason-code.

The __tf_parms_s structure is defined as follows:

typedef struct __tf_string_s {
     size_t     __tf_bufflen; 

     char*   __tf_buff; 
} __tf_string_t;
 
typedef struct __tf_parms_s {                                            
     /****************************************************************/ 
     /* Input                                                        */ 
     /****************************************************************/
     void*   __tf_dsa_addr;
     void*   __tf_caa_addr;
     void*   __tf_call_instruction;
     /****************************************************************/
     /* Output related to input DSA                                  */
     /****************************************************************/
     void*   __tf_ pu_addr;
     void*   __tf_ entry_addr;
     struct __cib*   __tf_cib_addr;
     uint8_t     __tf_member_id;
     int     __tf_is_main:1; 
     int     :23;
     int     :32; 
     __tf_string_t __tf_pu_name;
     __tf_string_t __tf_entry_name;
     __tf_string_t __tf_statement_id;
     /****************************************************************/
     /* Output related to caller's DSA                               */
     /****************************************************************/
     void*   __tf_caller_dsa_addr;
     void*   __tf_caller_call_instruction;
} __tf_parms_t;                                                                          
The following are members of the structure:
Member
Description
void* __tf_dsa_addr
The address of the DSA for the current routine in the traceback. When this field is zero on input, the address of the DSA for the caller of __le_traceback() will be used and the address will be returned. No attempt is made to verify that the input is a DSA. Incorrect input can lead to unpredictable results.
void* __tf_caa_addr
The address of the CAA associated with the DSA. When this field is zero on input, the address of the CAA for the current thread will be used and the address will be returned. No attempt is made to verify that the input is a CAA. Incorrect input can lead to unpredictable results.
void* __tf_call_instruction
The address of the instruction that caused transfer out of the routine. This is either the address of a BASR, BRAS or BRASL instruction if transfer was made by subroutine call, or the address of the interrupted statement if transfer was caused by an exception. When multiple calls are made to __le_traceback() to scan the call chain, the callers_call_instruction (described below) returned from the previous call can be used here. If the address is not known, this field should be set to zero. When this field is zero on input and the address can be determined, it will be returned.
void* __tf_pu_addr
The address of the start of the program unit for the routine associated with the DSA is returned in this field. If the program unit address cannot be determined, this field is set to zero.
void* __tf_entry_addr
The address of the entry point into the routine associated with the DSA is returned in this field. If the entry point address cannot be determined, this parameter is set to zero.
struct __cib* __tf_cib_addr
The address of the CIB (struct __cib) associated with the DSA, if an exception occurred, is returned in this field. If no exception occurred, this field is set to zero. Note that if an exception caused transfer out of the routine, the state of the registers after the last instruction ran in the routine is saved in the CIB, rather than in the DSA.
uint8_t __tf_member_id
The member identifier for the routine associated with the DSA will be returned in this field. If the member ID cannot be determined, this field is set to negative one.
int __tf_is_main:1
One of two values is returned in this field: 0 (the routine associated with the DSA is not the main program) or 1 (the routine associated with the DSA is the main program).
__tf_string_t __tf_pu_name
A structure that will be used to return the name of the program unit containing the routine associated with the DSA. The structure has the following fields:
char* __tf_buff
The address of a buffer in which the program unit name will be returned. The name will be returned in the buffer as a null terminated string.
size_t __tf_bufflen
The size of the buffer

If the program unit name cannot be determined, the buffer is set to a null string. If the program unit name cannot fit within the supplied string, it is truncated. (Truncation of DBCS preserves even byte count and SI/SO pairing.) If __tf_buff is NULL or __tf_bufflen is zero, the program unit name is not returned.

__tf_string_t __tf_entry_name
A structure that will be used to return the name of the entry point into the routine associated with the DSA. The structure has the following fields:
char* __tf_buff
The address of a buffer in which the entry point name will be returned. The name will be returned in the buffer as a null terminated string.
size_t __tf_bufflen
The size of the buffer

If the entry point name cannot be determined, the buffer is set to a null string. If the entry point name cannot fit within the supplied string, it is truncated. (Truncation of DBCS preserves even byte count and SI/SO pairing.) If __tf_buff is NULL or __tf_bufflen is zero, the entry point name is not returned

__tf_string_t __tf_statement_id
A structure that will be used to return the identifier of the statement containing the instruction which caused transfer out of the routine associated with the DSA. The structure has the following fields:
char* __tf_buff
The address of a buffer in which the statement id will be returned. The statement id will be returned in the buffer as a null terminated string.
size_t __tf_bufflen
The size of the buffer

If the statement id cannot be determined, the buffer is set to a null string. If the statement id cannot fit within the supplied string, it is truncated. (Truncation of DBCS preserves even byte count and SI/SO pairing.) If __tf_buff is NULL or __tf_bufflen is zero, the statement id is not returned

void* __tf_callers_dsa_addr
The address of the DSA for the caller is returned in this field. If the address of the caller's DSA cannot be determined or is not valid (points to inaccessible storage), then this field is set to zero.
void* __tf_callers_call_instruction
The address of the instruction that caused transfer out of the caller is returned in this field. This is either the address of a BASR, BRAS or BRASL instruction if transfer was made by subroutine call, or the address of the interrupted statement if transfer was caused by an exception. If the address cannot be determined, this parameter is set to zero.

Example

#include <__le_api.h>
#include <stdlib.h>

int main() {
  __tf_parms_t   tbck_parms;
  char                              pu_name[256];
  char                              entry_name[256];
  char                              statement_id[256];
  _FEEDBACK                         fc;
  int                               rc;


  tbck_parms.__tf_pu_name. __tf_bufflen = sizeof(pu_name);
  tbck_parms.__tf_entry_name. __tf_bufflen = sizeof(entry_name);
  tbck_parms.__tf_statement_id. __tf_bufflen = sizeof(statement_id);

  tbck_parms.__tf_pu_name. __tf_buff = pu_name;
  tbck_parms.__tf_entry_name. __tf_buff = entry_name;
  tbck_parms.__tf_statement_id. __tf_buff = statement_id;

  tbck_parms.__tf_dsa_addr = 0;
  tbck_parms.__tf_caa_addr = 0;
  tbck_parms.__tf_call_instruction = 0;

  do { 

    _le_traceback(__TRACEBACK_FIELDS, &tbck_parms, &fc);

    if ( fc.tok_sev >= 2 ) {
      printf("Error: __le_traceback() failed.\n");
      break;
    }

    printf("Entry=%s Offset=%c%x Line=%s\n",
           tbck_parms.__tf_entry_name.__tf_buff,
           tbck_parms.__tf_call_instruction  
           < tbck_parms.__tf_entry_addr ? '-' : '+',
           abs((int)((long)tbck_parms.__tf_call_instruction 
           - (long)tbck_parms.__tf_entry_addr)),
           tbck_parms.__tf_statement_id.__tf_buff
          );

    tbck_parms.__tf_dsa_addr = tbck_parms.__tf_caller_dsa_addr;
    tbck_parms.__tf_call_instruction =
       tbck_parms.__tf_caller_call_instruction;


  } while (!tbck_parms.__tf_is_main);

  return 0;
}
Output
Entry=main Offset=+da Line=28
Entry=CELQINIT Offset=+134c Line=

Related information