00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "absl/debugging/internal/examine_stack.h"
00018
00019 #ifndef _WIN32
00020 #include <unistd.h>
00021 #endif
00022
00023 #include <csignal>
00024 #include <cstdio>
00025
00026 #include "absl/base/attributes.h"
00027 #include "absl/base/internal/raw_logging.h"
00028 #include "absl/base/macros.h"
00029 #include "absl/debugging/stacktrace.h"
00030 #include "absl/debugging/symbolize.h"
00031
00032 namespace absl {
00033 namespace debugging_internal {
00034
00035
00036
00037
00038 void* GetProgramCounter(void* vuc) {
00039 #ifdef __linux__
00040 if (vuc != nullptr) {
00041 ucontext_t* context = reinterpret_cast<ucontext_t*>(vuc);
00042 #if defined(__aarch64__)
00043 return reinterpret_cast<void*>(context->uc_mcontext.pc);
00044 #elif defined(__arm__)
00045 return reinterpret_cast<void*>(context->uc_mcontext.arm_pc);
00046 #elif defined(__i386__)
00047 if (14 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs))
00048 return reinterpret_cast<void*>(context->uc_mcontext.gregs[14]);
00049 #elif defined(__mips__)
00050 return reinterpret_cast<void*>(context->uc_mcontext.pc);
00051 #elif defined(__powerpc64__)
00052 return reinterpret_cast<void*>(context->uc_mcontext.gp_regs[32]);
00053 #elif defined(__powerpc__)
00054 return reinterpret_cast<void*>(context->uc_mcontext.regs->nip);
00055 #elif defined(__s390__) && !defined(__s390x__)
00056 return reinterpret_cast<void*>(context->uc_mcontext.psw.addr & 0x7fffffff);
00057 #elif defined(__s390__) && defined(__s390x__)
00058 return reinterpret_cast<void*>(context->uc_mcontext.psw.addr);
00059 #elif defined(__x86_64__)
00060 if (16 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs))
00061 return reinterpret_cast<void*>(context->uc_mcontext.gregs[16]);
00062 #else
00063 #error "Undefined Architecture."
00064 #endif
00065 }
00066 #elif defined(__akaros__)
00067 auto* ctx = reinterpret_cast<struct user_context*>(vuc);
00068 return reinterpret_cast<void*>(get_user_ctx_pc(ctx));
00069 #endif
00070 static_cast<void>(vuc);
00071 return nullptr;
00072 }
00073
00074
00075
00076 static constexpr int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
00077
00078
00079
00080
00081
00082 static void DumpPCAndFrameSizeAndSymbol(void (*writerfn)(const char*, void*),
00083 void* writerfn_arg, void* pc,
00084 void* symbolize_pc, int framesize,
00085 const char* const prefix) {
00086 char tmp[1024];
00087 const char* symbol = "(unknown)";
00088 if (absl::Symbolize(symbolize_pc, tmp, sizeof(tmp))) {
00089 symbol = tmp;
00090 }
00091 char buf[1024];
00092 if (framesize <= 0) {
00093 snprintf(buf, sizeof(buf), "%s@ %*p (unknown) %s\n", prefix,
00094 kPrintfPointerFieldWidth, pc, symbol);
00095 } else {
00096 snprintf(buf, sizeof(buf), "%s@ %*p %9d %s\n", prefix,
00097 kPrintfPointerFieldWidth, pc, framesize, symbol);
00098 }
00099 writerfn(buf, writerfn_arg);
00100 }
00101
00102
00103 static void DumpPCAndFrameSize(void (*writerfn)(const char*, void*),
00104 void* writerfn_arg, void* pc, int framesize,
00105 const char* const prefix) {
00106 char buf[100];
00107 if (framesize <= 0) {
00108 snprintf(buf, sizeof(buf), "%s@ %*p (unknown)\n", prefix,
00109 kPrintfPointerFieldWidth, pc);
00110 } else {
00111 snprintf(buf, sizeof(buf), "%s@ %*p %9d\n", prefix,
00112 kPrintfPointerFieldWidth, pc, framesize);
00113 }
00114 writerfn(buf, writerfn_arg);
00115 }
00116
00117 void DumpPCAndFrameSizesAndStackTrace(
00118 void* pc, void* const stack[], int frame_sizes[], int depth,
00119 int min_dropped_frames, bool symbolize_stacktrace,
00120 void (*writerfn)(const char*, void*), void* writerfn_arg) {
00121 if (pc != nullptr) {
00122
00123 if (symbolize_stacktrace) {
00124 DumpPCAndFrameSizeAndSymbol(writerfn, writerfn_arg, pc, pc, 0, "PC: ");
00125 } else {
00126 DumpPCAndFrameSize(writerfn, writerfn_arg, pc, 0, "PC: ");
00127 }
00128 }
00129 for (int i = 0; i < depth; i++) {
00130 if (symbolize_stacktrace) {
00131
00132
00133
00134
00135
00136 DumpPCAndFrameSizeAndSymbol(writerfn, writerfn_arg, stack[i],
00137 reinterpret_cast<char*>(stack[i]) - 1,
00138 frame_sizes[i], " ");
00139 } else {
00140 DumpPCAndFrameSize(writerfn, writerfn_arg, stack[i], frame_sizes[i],
00141 " ");
00142 }
00143 }
00144 if (min_dropped_frames > 0) {
00145 char buf[100];
00146 snprintf(buf, sizeof(buf), " @ ... and at least %d more frames\n",
00147 min_dropped_frames);
00148 writerfn(buf, writerfn_arg);
00149 }
00150 }
00151
00152 }
00153 }