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
|
// modules.cpp — /proc/self/maps parsing and module discovery
#include "hl2h.h"
static bool basename_is(const char *path, const char *base) {
size_t pl = strlen(path), bl = strlen(base);
if (pl < bl || strcmp(path + pl - bl, base) != 0)
return false;
return pl == bl || path[pl - bl - 1] == '/';
}
void find_modules() {
g_client = Module();
g_engine = Module();
g_server = Module();
FILE *f = fopen("/proc/self/maps", "r");
if (!f)
return;
char line[1024];
while (fgets(line, sizeof(line), f)) {
unsigned long lo, hi;
char perms[8];
int consumed = 0;
if (sscanf(line, "%lx-%lx %7s %*x %*x:%*x %*u%n", &lo, &hi, perms,
&consumed) < 3)
continue;
if (perms[0] == '-' && perms[1] == '-' && perms[2] == '-')
continue; // PROT_NONE
const char *path = line + consumed;
while (*path == ' ' || *path == '\t')
path++;
size_t pl = strlen(path);
while (pl && (path[pl - 1] == '\n' || path[pl - 1] == '\r'))
pl--;
Module *m = nullptr;
char clean[1024];
if (pl && pl < sizeof(clean)) {
memcpy(clean, path, pl);
clean[pl] = 0;
if (basename_is(clean, "client.so"))
m = &g_client;
else if (basename_is(clean, "engine.so"))
m = &g_engine;
else if (basename_is(clean, "server.so"))
m = &g_server;
} else {
// anon: absorb only as .bss tail after a file-backed range
if (g_client.valid() && g_client.ranges.back().file &&
lo == g_client.ranges.back().hi && hi - lo <= 0x1000000)
m = &g_client;
else if (g_engine.valid() && g_engine.ranges.back().file &&
lo == g_engine.ranges.back().hi && hi - lo <= 0x1000000)
m = &g_engine;
}
if (!m)
continue;
if (m->ranges.empty()) {
if (!pl)
continue;
m->path = clean;
}
bool file = pl != 0;
if (!m->ranges.empty() && lo == m->ranges.back().hi) {
m->ranges.back().hi = hi;
m->ranges.back().file = m->ranges.back().file && file;
} else {
m->ranges.push_back({lo, hi, file});
}
}
fclose(f);
}
|