Skip to content

[z/OS] Add backtrace support for z/OS. #121826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions llvm/lib/Support/Unix/Signals.inc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
#undef HAVE__UNWIND_BACKTRACE
#endif
#endif
#if ENABLE_BACKTRACES && defined(__MVS__)
#include "llvm/Support/ConvertEBCDIC.h"
#include <__le_cwi.h>
#endif

using namespace llvm;

Expand Down Expand Up @@ -708,13 +712,86 @@ static int unwindBacktrace(void **StackTrace, int MaxEntries) {
}
#endif

#if ENABLE_BACKTRACES && defined(__MVS__)
static void zosbacktrace(raw_ostream &OS) {
// A function name in the PPA1 can have length 16k.
constexpr size_t MAX_ENTRY_NAME = UINT16_MAX;
// Limit all other strings to 8 byte.
constexpr size_t MAX_OTHER = 8;
int32_t dsa_format = -1; // Input/Output
void *caaptr = _gtca(); // Input
int32_t member_id; // Output
char compile_unit_name[MAX_OTHER]; // Output
void *compile_unit_address; // Output
void *call_instruction_address = nullptr; // Input/Output
char entry_name[MAX_ENTRY_NAME]; // Output
void *entry_address; // Output
void *callers_instruction_address; // Output
void *callers_dsaptr; // Output
int32_t callers_dsa_format; // Output
char statement_id[MAX_OTHER]; // Output
void *cibptr; // Output
int32_t main_program; // Output
_FEEDBACK fc; // Output

// The DSA pointer is the value of the stack pointer r4.
// __builtin_frame_address() returns a pointer to the stack frame, so the
// stack bias has to be considered to get the expected DSA value.
void *dsaptr = static_cast<char *>(__builtin_frame_address(0)) - 2048;
int count = 0;
OS << " DSA Adr EP +EP DSA "
" Entry\n";
while (1) {
// After the call, these variables contain the length of the string.
int32_t compile_unit_name_length = sizeof(compile_unit_name);
int32_t entry_name_length = sizeof(entry_name);
int32_t statement_id_length = sizeof(statement_id);
// See
// https://www.ibm.com/docs/en/zos/3.1.0?topic=cwicsa6a-celqtbck-also-known-as-celqtbck-64-bit-traceback-service
// for documentation of the parameters.
__CELQTBCK(&dsaptr, &dsa_format, &caaptr, &member_id, &compile_unit_name[0],
&compile_unit_name_length, &compile_unit_address,
&call_instruction_address, &entry_name[0], &entry_name_length,
&entry_address, &callers_instruction_address, &callers_dsaptr,
&callers_dsa_format, &statement_id[0], &statement_id_length,
&cibptr, &main_program, &fc);
if (fc.tok_sev) {
OS << format("error: CELQTBCK returned severity %d message %d\n",
fc.tok_sev, fc.tok_msgno);
break;
}

if (count) { // Omit first entry.
uintptr_t diff = reinterpret_cast<uintptr_t>(call_instruction_address) -
reinterpret_cast<uintptr_t>(entry_address);
OS << format(" %3d. 0x%016lX", count, call_instruction_address);
OS << format(" 0x%016lX +0x%08lX 0x%016lX", entry_address, diff, dsaptr);
SmallString<256> Str;
ConverterEBCDIC::convertToUTF8(StringRef(entry_name, entry_name_length),
Str);
OS << ' ' << Str << '\n';
}
++count;
if (callers_dsaptr) {
dsaptr = callers_dsaptr;
dsa_format = callers_dsa_format;
call_instruction_address = callers_instruction_address;
} else
break;
}
}
#endif

// In the case of a program crash or fault, print out a stack trace so that the
// user has an indication of why and where we died.
//
// On glibc systems we have the 'backtrace' function, which works nicely, but
// doesn't demangle symbols.
void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) {
#if ENABLE_BACKTRACES
#ifdef __MVS__
zosbacktrace(OS);
#else
static void *StackTrace[256];
int depth = 0;
#if defined(HAVE_BACKTRACE)
Expand Down Expand Up @@ -791,6 +868,7 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) {
backtrace_symbols_fd(StackTrace, Depth, STDERR_FILENO);
#endif
#endif
#endif
}

static void PrintStackTraceSignalHandler(void *) {
Expand Down
Loading