-
Notifications
You must be signed in to change notification settings - Fork 1
/
Base.cpp
82 lines (66 loc) · 1.91 KB
/
Base.cpp
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
#include "memory_patch.h"
#include <unordered_map>
#include <stdexcept>
#include <sstream>
#include <iomanip>
#include <assert.h>
#include <string.h>
#include <execinfo.h>
namespace memory_patch {
struct PatchData {
size_t m_len;
std::string m_backtrace;
};
using PatchDataMap = std::unordered_map<uintptr_t, PatchData>;
static PatchDataMap& GetPatchMap()
{
static auto map = new PatchDataMap();
return *map;
}
Base::Base(void* addr, size_t len, size_t expect_len, const void* expect) :
m_addr(addr), m_len(len)
{
assert(addr);
assert(len);
// Make sure the memory at the given location matches what we expect.
if (expect_len > 0 && expect != nullptr && memcmp(addr, expect, expect_len)) {
std::stringstream serr;
serr << "memory location at 0x" <<
std::setfill('0') << std::setw(8) << std::hex << addr <<
" did not have expected value (incompatible binary or something else patched it)";
throw std::runtime_error(serr.str());
}
// Make sure the given addr and len do not overlap with any other
// existing patch.
for (auto& pair : GetPatchMap()) {
if (std::max((uintptr_t)addr, pair.first) <=
std::min((uintptr_t)addr + len, pair.first + pair.second.m_len)) {
std::stringstream serr;
serr << "memory location at 0x" <<
std::setfill('0') << std::setw(8) << std::hex << addr <<
" already patched by:\n" << pair.second.m_backtrace;
throw std::runtime_error(serr.str());
}
}
// Also store a backtrace of whoever has hooked us.
std::string sbt;
void* callstack[32];
int i = 0,
frames = backtrace(callstack, 32);
if (frames > 0) {
char** bt = backtrace_symbols(callstack, frames);
assert(bt);
for (i = 0; i < frames; ++i) {
sbt += std::string(bt[i]) + "\n";
}
free(bt);
} else
sbt = "(no backtrace available)";
PatchData pd = { len, sbt };
GetPatchMap()[(uintptr_t)addr] = pd;
}
Base::~Base()
{
GetPatchMap().erase((uintptr_t)m_addr);
}
}