-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[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
Conversation
@llvm/pr-subscribers-llvm-support Author: Kai Nacke (redstar) ChangesThe system call Full diff: https://github.com/llvm/llvm-project/pull/121826.diff 1 Files Affected:
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index 088ca33e3c8c56..2a1977b2c94a02 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -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;
@@ -708,6 +712,79 @@ static int unwindBacktrace(void **StackTrace, int MaxEntries) {
}
#endif
+#if ENABLE_BACKTRACES && defined(__MVS__)
+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;
+ void *dsaptr; // Input
+ int32_t dsa_format = -1; // Input/Output
+ void *caaptr = _gtca(); // Input
+ int32_t member_id;
+ char compile_unit_name[MAX_OTHER];
+ int32_t compile_unit_name_length = sizeof(compile_unit_name); // Input/Output
+ void *compile_unit_address; // Output
+ void *call_instruction_address = 0; // Input/Output
+ char entry_name[MAX_ENTRY_NAME]; // Output
+ int32_t entry_name_length = sizeof(entry_name); // Input/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
+ int32_t statement_id_length = sizeof(statement_id); // Input/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.
+ dsaptr = static_cast<char *>(__builtin_frame_address(0)) - 2048;
+ int count = 0;
+ OS << " DSA Adr EP +EP DSA "
+ " Entry\n";
+ while (1) {
+ compile_unit_name_length = sizeof(compile_unit_name);
+ entry_name_length = sizeof(entry_name);
+ 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! 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%016X", count, call_instruction_address);
+ OS << format(" 0x%016X +0x%08X 0x%016X", entry_address, diff, dsaptr);
+ SmallString<256> Str;
+ ConverterEBCDIC::convertToUTF8(StringRef(entry_name, entry_name_length),
+ Str);
+ OS << format(" %s", Str.c_str());
+ OS << "\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.
//
@@ -715,6 +792,9 @@ static int unwindBacktrace(void **StackTrace, int MaxEntries) {
// 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)
@@ -791,6 +871,7 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) {
backtrace_symbols_fd(StackTrace, Depth, STDERR_FILENO);
#endif
#endif
+#endif
}
static void PrintStackTraceSignalHandler(void *) {
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
The system call `__CELQTBCK()` is used to build a backtrace like on other systems. The collected information are the address of the PC, the address of the entry point (EP), the difference between both addresses (+EP), the dynamic storage area (DSA aka the stack pointer), and the function name. The system call is described here: https://www.ibm.com/docs/en/zos/3.1.0?topic=cwicsa6a-celqtbck-also-known-as-celqtbck-64-bit-traceback-service
df700ff
to
2992483
Compare
The system call `__CELQTBCK()` is used to build a backtrace like on other systems. The collected information are the address of the PC, the address of the entry point (EP), the difference between both addresses (+EP), the dynamic storage area (DSA aka the stack pointer), and the function name. The system call is described here: https://www.ibm.com/docs/en/zos/3.1.0?topic=cwicsa6a-celqtbck-also-known-as-celqtbck-64-bit-traceback-service
The system call
__CELQTBCK()
is used to build a backtrace likeon other systems. The collected information are the address of the PC,
the address of the entry point (EP), the difference between both
addresses (+EP), the dynamic storage area (DSA aka the stack
pointer), and the function name.
The system call is described here:
https://www.ibm.com/docs/en/zos/3.1.0?topic=cwicsa6a-celqtbck-also-known-as-celqtbck-64-bit-traceback-service