-
Notifications
You must be signed in to change notification settings - Fork 53
/
callstack.c
75 lines (73 loc) · 2.31 KB
/
callstack.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
* @file tlib/callstack.c
*
* @copyright 2014-2020 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
}