-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathmisc.cpp
More file actions
122 lines (112 loc) · 3.25 KB
/
misc.cpp
File metadata and controls
122 lines (112 loc) · 3.25 KB
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <array>
#include <execinfo.h>
#include <memory>
#include <sys/stat.h>
#include <sstream>
#include "misc.h"
std::string hex_dump(const char *begin, const char *end, const char *pos)
{
std::string res;
res.reserve(static_cast<size_t>((end - begin)) * 4);
constexpr char hexmap[] = {"0123456789abcdef"};
int cnt = 0;
for (const char* c = begin; c < end; ++c)
{
++cnt;
char sep = ' ';
if (pos)
{
if (c == pos - 1)
sep = '>';
else if (c == pos)
sep = '<';
}
res += hexmap[(*c & 0xF0) >> 4];
res += hexmap[*c & 0x0F];
res += sep;
if (cnt % 16 == 0)
res += '\n';
else if (cnt % 8 == 0)
res += ' ';
}
return res;
}
std::string get_trace()
{
void *array[10];
const size_t size = backtrace(array, 10);
char **strings = backtrace_symbols(array, size);
if (!strings)
return "unable to acquire backtrace symbols";
std::unique_ptr<char*, void(*)(char**)> sguard(strings, [](char **s) { free(s); });
std::string error;
std::stringstream s;
// skip this handler
for (size_t i = 1; i < size; i++)
{
// extract the exe name
std::string exe(strings[i]);
{
const size_t s = exe.find("(");
if(std::string::npos != s)
exe.erase(s, exe.length());
struct stat tmp;
if (stat(exe.c_str(), &tmp) != 0)
exe.clear();
}
// extract the address
std::string addr(strings[i]);
{
size_t s = addr.find("(");
if (std::string::npos != s)
{
++s;
addr.erase(0, s);
s = addr.find(")");
if(std::string::npos != s)
addr.erase(s, addr.length());
else
addr.clear();
}
else
{
addr.clear();
}
}
s << '[' << i << "]: " << strings[i];
if (error.empty() && !exe.empty() && !addr.empty())
{
char cmd[1024];
sprintf(cmd, "addr2line -s -a -p -f -C -e %s %s 2>&1", exe.c_str(), addr.c_str());
std::array<char, 128> buffer;
std::string placement;
int stat = 0;
int wstat = 0;
auto deleter = [&error, &stat, &wstat](FILE * f)
{
stat = pclose(f);
wstat = WEXITSTATUS(stat);
};
std::unique_ptr<FILE, decltype(deleter)> pipe(popen(cmd, "r"), deleter);
if (pipe)
{
while (fgets(buffer.data(), static_cast<int>(buffer.size()), pipe.get()) != nullptr)
placement += buffer.data();
pipe.release();
if (stat < 0 || (wstat != 0 && wstat != 128 + 13/*SIGPIPE*/))
error = placement;
else if (!placement.empty())
s << " -> " << placement;
else
s << "\n";
}
}
else
{
s << "\n";
}
}
if (!error.empty())
s << "\n" << error;
return s.str();
}