Created
July 4, 2020 05:52
-
-
Save vikaschoudhary16/d07f897c75da5b2d0f23ba1fa8ed219c to your computer and use it in GitHub Desktop.
envoy-debugging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vikas@ proxy ((HEAD detached at d2d90deb)) $ cat extensions/metadata_exchange/backtrace.h | |
#pragma once | |
#include <functional> | |
#include "absl/debugging/stacktrace.h" | |
#include "absl/debugging/symbolize.h" | |
#include "common/common/logger.h" | |
//#include "common/common/version.h" | |
namespace Plugin { | |
#define BACKTRACE_LOG() \ | |
do { \ | |
::Plugin::BackwardsTrace t; \ | |
t.capture(); \ | |
t.logTrace(); \ | |
} while (0) | |
/** | |
* Use absl::Stacktrace and absl::Symbolize to log resolved symbols | |
* stack traces on demand. To use this just do: | |
* | |
* BackwardsTrace tracer; | |
* tracer.capture(); // Trace is captured as of here. | |
* tracer.logTrace(); // Output the captured trace to the log. | |
* | |
* The capture and log steps are separated to enable debugging in the case where | |
* you want to capture a stack trace from inside some logic but don't know | |
* whether you want to bother logging it until later. | |
* | |
* For convenience a macro is provided BACKTRACE_LOG() which performs the | |
* construction, capture, and log in one shot. | |
* | |
* If the symbols cannot be resolved by absl::Symbolize then the raw address | |
* will be printed instead. | |
*/ | |
class BackwardsTrace : Envoy::Logger::Loggable<Envoy::Logger::Id::backtrace> { | |
public: | |
BackwardsTrace() = default; | |
/** | |
* Capture a stack trace. | |
* | |
* The trace will begin with the call to capture(). | |
*/ | |
void capture() { | |
// Skip of one means we exclude the last call, which must be to capture(). | |
stack_depth_ = | |
absl::GetStackTrace(stack_trace_, MaxStackDepth, /* skip_count = */ 1); | |
} | |
/** | |
* Capture a stack trace from a particular context. | |
* | |
* This can be used to capture a useful stack trace from a fatal signal | |
* handler. The context argument should be a pointer to the context passed | |
* to a signal handler registered via a sigaction struct. | |
* | |
* @param context A pointer to ucontext_t obtained from a sigaction handler. | |
*/ | |
void captureFrom(const void* context) { | |
stack_depth_ = absl::GetStackTraceWithContext( | |
stack_trace_, MaxStackDepth, /* skip_count = */ 1, context, | |
/* min_dropped_frames = */ nullptr); | |
} | |
/** | |
* Log the stack trace. | |
*/ | |
void logTrace() { | |
ENVOY_LOG(critical, | |
"Backtrace (use tools/stack_decode.py to get line numbers):"); | |
visitTrace([](int index, const char* symbol, void* address) { | |
if (symbol != nullptr) { | |
ENVOY_LOG(critical, "#{}: {} [{}]", index, symbol, address); | |
} else { | |
ENVOY_LOG(critical, "#{}: [{}]", index, address); | |
} | |
}); | |
} | |
void logFault(const char* signame, const void* addr) { | |
ENVOY_LOG(critical, "Caught {}, suspect faulting address {}", signame, | |
addr); | |
} | |
void printTrace(std::ostream& os) { | |
visitTrace([&](int index, const char* symbol, void* address) { | |
if (symbol != nullptr) { | |
os << "#" << index << " " << symbol << " [" << address << "]\n"; | |
} else { | |
os << "#" << index << " [" << address << "]\n"; | |
} | |
}); | |
} | |
private: | |
/** | |
* Visit the previously captured stack trace. | |
* | |
* The visitor function is called once per frame, with 3 parameters: | |
* 1. (int) The index of the current frame. | |
* 2. (const char*) The symbol name for the address of the current frame. | |
* nullptr means symbolization failed. | |
* 3. (void*) The address of the current frame. | |
*/ | |
void visitTrace(const std::function<void(int, const char*, void*)>& visitor) { | |
for (int i = 0; i < stack_depth_; ++i) { | |
char out[1024]; | |
const bool success = absl::Symbolize(stack_trace_[i], out, sizeof(out)); | |
if (success) { | |
visitor(i, out, stack_trace_[i]); | |
} else { | |
visitor(i, nullptr, stack_trace_[i]); | |
} | |
} | |
} | |
static constexpr int MaxStackDepth = 64; | |
void* stack_trace_[MaxStackDepth]; | |
int stack_depth_{0}; | |
}; | |
} // namespace Plugin |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment