123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- #include "demangle_impl.h"
- #include "platform.h"
- #include "backtrace.h"
- #include <util/stream/output.h>
- #include <util/stream/format.h>
- #include <util/generic/array_ref.h>
- #include <util/generic/string.h>
- #ifdef _win_
- #include "mutex.h"
- #ifndef OPTIONAL
- #define OPTIONAL
- #endif
- #include <dbghelp.h>
- #endif
- #if defined(_bionic_)
- // TODO
- #else
- #if !defined(HAVE_BACKTRACE) && defined(_cygwin_)
- #define CaptureStackBackTrace RtlCaptureStackBackTrace
- extern "C" __stdcall unsigned short CaptureStackBackTrace(unsigned long FramesToSkip, unsigned long FramesToCapture, void** BackTrace, unsigned long* BackTraceHash);
- #define USE_WIN_BACKTRACE
- #define HAVE_BACKTRACE
- #endif
- #if !defined(HAVE_BACKTRACE) && defined(__IOS__)
- #define USE_GLIBC_BACKTRACE
- #define HAVE_BACKTRACE
- #endif
- #if !defined(HAVE_BACKTRACE) && defined(__GNUC__)
- #define USE_GCC_BACKTRACE
- #define HAVE_BACKTRACE
- #endif
- #if !defined(HAVE_BACKTRACE) && defined(_win_)
- #define USE_WIN_BACKTRACE
- #define HAVE_BACKTRACE
- #endif
- #if !defined(HAVE_BACKTRACE) && defined(_glibc_)
- #define USE_GLIBC_BACKTRACE
- #define HAVE_BACKTRACE
- #endif
- #endif
- #if defined(USE_GLIBC_BACKTRACE)
- #include <execinfo.h>
- size_t BackTrace(void** p, size_t len) {
- return (size_t)backtrace(p, len);
- }
- #endif
- #if defined(USE_GCC_BACKTRACE)
- #include <cxxabi.h>
- #include <unwind.h>
- namespace {
- namespace NGCCBacktrace {
- struct TBackTraceContext {
- void** sym;
- size_t cnt;
- size_t size;
- };
- static _Unwind_Reason_Code Helper(struct _Unwind_Context* c, void* h) {
- TBackTraceContext* bt = (TBackTraceContext*)h;
- if (bt->cnt != 0) {
- bt->sym[bt->cnt - 1] = (void*)_Unwind_GetIP(c);
- }
- if (bt->cnt == bt->size) {
- return _URC_END_OF_STACK;
- }
- ++bt->cnt;
- return _URC_NO_REASON;
- }
- static inline size_t BackTrace(void** p, size_t len) {
- if (len >= 1) {
- TBackTraceContext bt = {p, 0, len};
- _Unwind_Backtrace(Helper, &bt);
- return bt.cnt - 1;
- }
- return 0;
- }
- } // namespace NGCCBacktrace
- } // namespace
- size_t BackTrace(void** p, size_t len) {
- return NGCCBacktrace::BackTrace(p, len);
- }
- #endif
- #if defined(USE_WIN_BACKTRACE)
- size_t BackTrace(void** p, size_t len) {
- return CaptureStackBackTrace(0, len, p, nullptr);
- }
- #endif
- #if !defined(HAVE_BACKTRACE)
- size_t BackTrace(void**, size_t) {
- return 0;
- }
- #endif
- #if defined(_unix_) && !defined(_cygwin_)
- #include <util/generic/strfcpy.h>
- #include <dlfcn.h>
- #if defined(_darwin_)
- #include <execinfo.h>
- #endif
- static inline const char* CopyTo(const char* from, char* buf, size_t len) {
- strfcpy(buf, from, len);
- return buf;
- }
- TResolvedSymbol ResolveSymbol(void* sym, char* buf, size_t len) {
- TResolvedSymbol ret = {
- "??",
- sym,
- };
- Dl_info dli;
- Zero(dli);
- if (dladdr(sym, &dli) && dli.dli_sname) {
- ret.Name = CopyTo(NPrivate::TCppDemangler().Demangle(dli.dli_sname), buf, len);
- ret.NearestSymbol = dli.dli_saddr;
- }
- return ret;
- }
- #elif defined(_win_)
- #include <util/generic/singleton.h>
- namespace {
- struct TWinSymbolResolverImpl {
- typedef BOOL(WINAPI* TSymInitializeFunc)(HANDLE, PCSTR, BOOL);
- typedef BOOL(WINAPI* TSymCleanupFunc)(HANDLE);
- typedef BOOL(WINAPI* TSymFromAddrFunc)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
- TWinSymbolResolverImpl()
- : InitOk(FALSE)
- {
- Library = LoadLibraryA("Dbghelp.dll");
- if (!Library) {
- return;
- }
- SymInitializeFunc = (TSymInitializeFunc)GetProcAddress(Library, "SymInitialize");
- SymCleanupFunc = (TSymCleanupFunc)GetProcAddress(Library, "SymCleanup");
- SymFromAddrFunc = (TSymFromAddrFunc)GetProcAddress(Library, "SymFromAddr");
- if (SymInitializeFunc && SymCleanupFunc && SymFromAddrFunc) {
- InitOk = SymInitializeFunc(GetCurrentProcess(), nullptr, TRUE);
- }
- }
- ~TWinSymbolResolverImpl() {
- if (InitOk) {
- SymCleanupFunc(GetCurrentProcess());
- }
- if (Library) {
- FreeLibrary(Library);
- }
- }
- TResolvedSymbol Resolve(void* sym, char* buf, size_t len) {
- TGuard<TMutex> guard(Mutex);
- TResolvedSymbol ret = {
- "??",
- sym};
- if (!InitOk || (len <= 1 + sizeof(SYMBOL_INFO))) {
- return ret;
- }
- SYMBOL_INFO* symbol = (SYMBOL_INFO*)buf;
- Zero(*symbol);
- symbol->MaxNameLen = len - sizeof(SYMBOL_INFO) - 1;
- symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
- DWORD64 displacement = 0;
- BOOL res = SymFromAddrFunc(GetCurrentProcess(), (DWORD64)sym, &displacement, symbol);
- if (res) {
- ret.NearestSymbol = (void*)symbol->Address;
- ret.Name = symbol->Name;
- }
- return ret;
- }
- TMutex Mutex;
- HMODULE Library;
- TSymInitializeFunc SymInitializeFunc;
- TSymCleanupFunc SymCleanupFunc;
- TSymFromAddrFunc SymFromAddrFunc;
- BOOL InitOk;
- };
- } // namespace
- TResolvedSymbol ResolveSymbol(void* sym, char* buf, size_t len) {
- return Singleton<TWinSymbolResolverImpl>()->Resolve(sym, buf, len);
- }
- #else
- TResolvedSymbol ResolveSymbol(void* sym, char*, size_t) {
- TResolvedSymbol ret = {
- "??",
- sym,
- };
- return ret;
- }
- #endif
- void FormatBackTrace(IOutputStream* out, void* const* backtrace, size_t backtraceSize) {
- char tmpBuf[1024];
- for (size_t i = 0; i < backtraceSize; ++i) {
- TResolvedSymbol rs = ResolveSymbol(backtrace[i], tmpBuf, sizeof(tmpBuf));
- *out << rs.Name << "+" << ((ptrdiff_t)backtrace[i] - (ptrdiff_t)rs.NearestSymbol) << " (" << Hex((ptrdiff_t)backtrace[i], HF_ADDX) << ')' << '\n';
- }
- }
- TFormatBackTraceFn FormatBackTraceFn = FormatBackTrace;
- TFormatBackTraceFn SetFormatBackTraceFn(TFormatBackTraceFn f) {
- TFormatBackTraceFn prevFn = FormatBackTraceFn;
- FormatBackTraceFn = f;
- return prevFn;
- }
- void FormatBackTrace(IOutputStream* out) {
- void* array[300];
- const size_t s = BackTrace(array, Y_ARRAY_SIZE(array));
- FormatBackTraceFn(out, array, s);
- }
- TFormatBackTraceFn GetFormatBackTraceFn() {
- return FormatBackTraceFn;
- }
- void PrintBackTrace() {
- FormatBackTrace(&Cerr);
- }
- TBackTrace::TBackTrace()
- : Size(0)
- {
- }
- void TBackTrace::Capture() {
- Size = BackTrace(Data, CAPACITY);
- }
- void TBackTrace::PrintTo(IOutputStream& out) const {
- FormatBackTraceFn(&out, Data, Size);
- }
- TString TBackTrace::PrintToString() const {
- TStringStream ss;
- PrintTo(ss);
- return ss.Str();
- }
- size_t TBackTrace::size() const {
- return Size;
- }
- const void* const* TBackTrace::data() const {
- return Data;
- }
- TBackTrace::operator TBackTraceView() const {
- return TBackTraceView(Data, Size);
- }
- TBackTrace TBackTrace::FromCurrentException() {
- #ifdef _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_SIZE
- TBackTrace result;
- result.Size = __cxxabiv1::__cxa_collect_current_exception_backtrace(result.Data, CAPACITY);
- return result;
- #else
- return TBackTrace();
- #endif
- }
|