mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
76 lines
2.3 KiB
C
76 lines
2.3 KiB
C
/**
|
|
* @file tlib/callstack.c
|
|
*
|
|
* @copyright 2014-2022 Bill Zissimopoulos
|
|
*/
|
|
|
|
#include <tlib/callstack.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
#include <windows.h>
|
|
#include <dbghelp.h>
|
|
#pragma comment(lib, "dbghelp.lib")
|
|
#elif defined(__APPLE__) || defined(__linux__)
|
|
#include <dlfcn.h>
|
|
#include <execinfo.h>
|
|
#else
|
|
#error tlib/callstack.c not implemented for this platform
|
|
#endif
|
|
|
|
void tlib_callstack(size_t skip, size_t count, struct tlib_callstack_s *stack)
|
|
{
|
|
if (count > TLIB_MAX_SYMRET)
|
|
count = TLIB_MAX_SYMRET;
|
|
size_t naddrs = skip + count;
|
|
if (naddrs > TLIB_MAX_SYMCAP)
|
|
naddrs = TLIB_MAX_SYMCAP;
|
|
memset((void *)stack->syms, 0, sizeof stack->syms);
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
/* SymInitialize()/SymFromAddr() are not thread-safe. Furthermore SymInitialize() should
|
|
* not be called more than once per process.
|
|
*/
|
|
HANDLE hproc = GetCurrentProcess();
|
|
static SYMBOL_INFO *syminfo = 0;
|
|
void *addrs[TLIB_MAX_SYMCAP];
|
|
size_t i = 0;
|
|
if (0 == syminfo)
|
|
{
|
|
syminfo = (SYMBOL_INFO *)malloc(sizeof(SYMBOL_INFO) + TLIB_MAX_SYMLEN);
|
|
if (0 == syminfo)
|
|
return;
|
|
SymInitialize(hproc, 0, TRUE);
|
|
}
|
|
memset(syminfo, 0, sizeof(SYMBOL_INFO));
|
|
syminfo->SizeOfStruct = sizeof(SYMBOL_INFO);
|
|
syminfo->MaxNameLen = TLIB_MAX_SYMLEN;
|
|
naddrs = CaptureStackBackTrace(0, naddrs, addrs, 0);
|
|
for (void **p = addrs + skip, **endp = addrs + naddrs; endp > p; p++)
|
|
{
|
|
DWORD64 displacement = 0;
|
|
if (SymFromAddr(hproc, (DWORD64)*p, &displacement, syminfo))
|
|
{
|
|
stack->syms[i] = stack->symbuf[i];
|
|
strncpy(stack->symbuf[i], syminfo->Name, TLIB_MAX_SYMLEN);
|
|
stack->symbuf[i][TLIB_MAX_SYMLEN] = '\0';
|
|
i++;
|
|
}
|
|
}
|
|
#elif defined(__APPLE__) || defined(__linux__)
|
|
void *addrs[TLIB_MAX_SYMCAP];
|
|
naddrs = backtrace(addrs, naddrs);
|
|
size_t i = 0;
|
|
Dl_info syminfo;
|
|
for (void **p = addrs + skip, **endp = addrs + naddrs; endp > p; p++)
|
|
{
|
|
if (dladdr(*p, &syminfo) && 0 != syminfo.dli_sname)
|
|
{
|
|
stack->syms[i] = stack->symbuf[i];
|
|
strncpy(stack->symbuf[i], syminfo.dli_sname, TLIB_MAX_SYMLEN);
|
|
stack->symbuf[i][TLIB_MAX_SYMLEN] = '\0';
|
|
i++;
|
|
}
|
|
}
|
|
#endif
|
|
}
|