Skip to content
This repository was archived by the owner on Nov 1, 2024. It is now read-only.

Commit bbea1ee

Browse files
authored
Merge DevBranch: SymDB2
read All the symbols to memory, provide Super Fast dlsym switch to SymDB2, which is faster than before
2 parents b1c4e6c + 9b37c38 commit bbea1ee

File tree

9 files changed

+304
-130
lines changed

9 files changed

+304
-130
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,17 @@ jobs:
4545
unzip D:/cc.zip
4646
shell: bash
4747

48-
- name: Download RoDB.exe
48+
- name: Copy SymDB2 Gen
49+
working-directory: ${{env.GITHUB_WORKSPACE}}
4950
run: |
50-
curl -L -o D:/out/release/RoDB.exe https://github.com/Sysca11/BDXCore/raw/master/RoDB.exe
51+
cp -a Tool/SymDB2.exe D:/out/release
5152
shell: bash
5253

5354
- name: Copy Output Files
5455
working-directory: ${{env.GITHUB_WORKSPACE}}
5556
run: |
5657
cp -a x64/Release/*.dll D:/out/release
57-
cp -a D:/cc/x64_release/ChakraCore.dll D:/out/release
58-
58+
cp -a D:/cc/x64_release/ChakraCore.dll D:/out/release
5959
shell: bash
6060

6161
- name: Copy DevOutput Files

LiteLoader/LiteLoader.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ void FixUpCWD() {
117117
void startWBThread();
118118
bool versionCommand(CommandOrigin const &ori, CommandOutput &outp);
119119
void updateCheck();
120-
121120
static void entry(bool fixcwd) {
122121
//禁止弹窗,便于自动重启
123122
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOALIGNMENTFAULTEXCEPT);

LiteLoader/dlsym.cpp

Lines changed: 206 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -15,136 +15,237 @@
1515
using std::list;
1616
using std::string, std::string_view;
1717
using std::unordered_map, std::vector;
18-
19-
typedef unsigned long long hash_t;
20-
hash_t BKDR(const char *_ch, size_t sz) {
21-
unsigned char *ch = (unsigned char *)_ch;
22-
hash_t rv = 0;
23-
for (int i = 0; i < sz; ++i) {
24-
rv = rv * 127 - 36 + ch[i];
18+
struct aphash {
19+
size_t operator()(const string &x) const {
20+
uint64_t rval = 0;
21+
for (size_t i = 0; x[i]; ++i) {
22+
if (i & 1) {
23+
rval ^= (~((rval << 11) ^ x[i] ^ (rval >> 5)));
24+
} else {
25+
rval ^= (~((rval << 7) ^ x[i] ^ (rval >> 3)));
26+
}
27+
}
28+
return rval;
2529
}
26-
return rv;
27-
}
28-
struct hashval {
29-
string key;
30-
hash_t hash;
31-
string data;
32-
hashval() { hash = 0; }
33-
hashval(string &&a, hash_t b, string &&c)
34-
: key(std::forward<string>(a)), hash(b), data(std::forward<string>(c)) {}
3530
};
36-
struct RoDB_R {
37-
std::ifstream fp;
38-
unsigned int cnt_bucket;
39-
unsigned int bucket[4096]; // offset
40-
unsigned int data_off;
41-
RoDB_R(const char *path) {
42-
fp.open(path, std::ios::binary);
43-
#define ppch(x) ((char *)&x)
44-
fp.read(ppch(cnt_bucket), 4);
45-
fp.read(ppch(data_off), 4);
46-
fp.read(ppch(bucket[0]), 4 * (size_t)cnt_bucket);
31+
struct SymDBBase {
32+
// constexpr static int SEGMENT_MAX = 8;
33+
constexpr static int SEGMENT_HASH_ORDERED = 0;
34+
constexpr static int SEGMENT_RVA_INT = 1;
35+
constexpr static int SEGMENT_STRINGS_IDX = 2;
36+
constexpr static int SEGMENT_STRINGS = 3;
37+
constexpr static int SEGMENT_COUNT = 4;
38+
};
39+
#include <vector>
40+
typedef int s32;
41+
typedef int64_t s64;
42+
typedef uint64_t u64;
43+
typedef uint32_t u32;
44+
typedef uint16_t u16;
45+
typedef uint8_t u8;
46+
template <int BKDR_MUL = 131, int BKDR_ADD = 0>
47+
constexpr u64 BKDRHash(const char *x, int len) {
48+
u64 rval = 0;
49+
for (size_t i = 0; i < len; ++i) {
50+
rval *= BKDR_MUL;
51+
rval += x[i];
52+
rval += BKDR_ADD;
4753
}
48-
void read(void *buf, unsigned int off, size_t sz) {
49-
fp.seekg(std::streampos(off));
50-
fp.read((char *)buf, sz);
54+
return rval;
55+
}
56+
#include <algorithm>
57+
#include <fstream>
58+
59+
struct SymDBReader : SymDBBase {
60+
int SEGOFF[SEGMENT_COUNT], SIZSEG[SEGMENT_COUNT];
61+
std::ifstream ifs;
62+
u64 *hashes;
63+
u64 *hashes_end;
64+
template <typename T>
65+
T _pfread(int off = -1) {
66+
if (off != -1)
67+
ifs.seekg({off});
68+
T rv;
69+
ifs.read((char *)&rv, sizeof(T));
70+
return rv;
5171
}
52-
void getstr(string &buf, unsigned int off) {
53-
if (off != 0) {
54-
fp.seekg(std::streampos(off));
72+
SymDBReader(const char *fn) {
73+
ifs.open(fn, std::ios::binary);
74+
for (int &off : SEGOFF) {
75+
off = _pfread<int>();
76+
}
77+
for (int &siz : SIZSEG) {
78+
siz = _pfread<int>();
79+
}
80+
if (SEGOFF[0] != 8 * SEGMENT_COUNT) {
81+
printf("SymDB format error detected!!\n");
5582
}
56-
char ch;
57-
while ((ch = fp.get()) != 0)
58-
buf.append(1, ch);
83+
int seg_begin = SEGOFF[SEGMENT_HASH_ORDERED];
84+
int seg_siz = SIZSEG[SEGMENT_HASH_ORDERED];
85+
char *buf = (char *)malloc(seg_siz);
86+
ifs.seekg({seg_begin});
87+
ifs.read(buf, seg_siz);
88+
hashes = (u64 *)buf;
89+
hashes_end = hashes + (seg_siz / 8);
5990
}
60-
string val2key(unsigned int rva) {
61-
fp.seekg(std::streampos(data_off));
62-
string name;
63-
name.reserve(8192);
64-
while (!fp.eof()) {
65-
int ch = fp.get();
66-
if (ch == 0) {
67-
unsigned int dst;
68-
fp.read((char *)&dst, 4);
69-
if (dst == rva) {
70-
return name;
71-
} else {
72-
name.clear();
91+
~SymDBReader() { free(hashes); }
92+
int lookupInternal(u64 hash, int length, u64 hash2, const char *symname) {
93+
// step 1:lookup internal index
94+
u64 *lbound = std::lower_bound(hashes, hashes_end, hash);
95+
if (lbound == hashes_end || *lbound != hash)
96+
return -1;
97+
int internalIdx = int(std::distance(hashes, lbound));
98+
int matchCount = 0;
99+
for (u64 *start = lbound; start < hashes_end; ++start) {
100+
if (*start == hash)
101+
++matchCount;
102+
else
103+
break;
104+
}
105+
// printf("internalIdx [%d,%d)\n", internalIdx, internalIdx+matchCount);
106+
// step 2:load string offsets
107+
ifs.seekg({SEGOFF[SEGMENT_STRINGS_IDX] + internalIdx * 4});
108+
int string_off[256];
109+
for (int i = 0; i <= matchCount; ++i) {
110+
// string_off[i] = _pfread<int>(SEGOFF[SEGMENT_STRINGS_IDX] + (internalIdx + i) * 4);
111+
string_off[i] = _pfread<int>();
112+
}
113+
int idx_hits[128];
114+
int siz_idx_hits = 0;
115+
for (int i = 0; i < matchCount; ++i) {
116+
int strlength = string_off[i + 1] - string_off[i];
117+
if (length == strlength) {
118+
idx_hits[siz_idx_hits++] = internalIdx + i;
119+
}
120+
}
121+
if (siz_idx_hits == 0) {
122+
return -1;
123+
}
124+
int retval = -1;
125+
for (int i = 0; i < siz_idx_hits; ++i) {
126+
int nowidx = idx_hits[i];
127+
int strptr = string_off[i] + SEGOFF[SEGMENT_STRINGS];
128+
ifs.seekg({strptr});
129+
if (symname != nullptr) {
130+
static constexpr auto CMPSTR = [](std::ifstream &ifs, const char *symname) -> bool {
131+
for (char const *compare = symname; *compare; ++compare) {
132+
if (*compare != ifs.get())
133+
return false;
134+
}
135+
return true;
136+
};
137+
if (CMPSTR(ifs, symname)) {
138+
return _pfread<int>(SEGOFF[SEGMENT_RVA_INT] + nowidx * 4);
73139
}
74140
} else {
75-
name.push_back(ch);
141+
static constexpr auto HASHSTR = [](std::ifstream &ifs, int len) -> u64 {
142+
u64 rv = 0;
143+
while (len-- > 0) {
144+
rv = 131 * rv + char(ifs.get());
145+
}
146+
return rv;
147+
};
148+
if (HASHSTR(ifs, length) == hash2) {
149+
if (retval != -1) {
150+
printf("hash coll detected!\n");
151+
exit(1);
152+
}
153+
retval = _pfread<int>(SEGOFF[SEGMENT_RVA_INT] + nowidx * 4);
154+
}
76155
}
77156
}
78-
return "(nil)";
157+
return retval;
79158
}
80-
bool _cmp(string_view key) {
81-
for (uint32_t i = 0; i < key.size(); ++i) {
82-
int ch = fp.get();
83-
if (ch != key[i]) {
84-
return false;
85-
}
86-
}
87-
return fp.get() == 0;
159+
int getsym(const char *name) {
160+
int len = int(strlen(name));
161+
return lookupInternal(do_hash(name, len), len, 0, name);
88162
}
89-
unsigned int get(string_view key) { // return file offset
90-
auto hash = BKDR(key.data(), key.size());
91-
auto bkoff = bucket[hash % cnt_bucket];
92-
fp.seekg(std::streampos(bkoff));
93-
vector<unsigned int> tolookup;
94-
tolookup.reserve(512);
95-
while (1) {
96-
hash_t hs;
97-
unsigned int off;
98-
fp.read(ppch(hs), 8);
99-
fp.read(ppch(off), 4);
100-
if (off == 0xffffffff)
101-
break;
102-
if (hs == hash)
103-
tolookup.push_back(off + data_off);
104-
/*
105-
if (hs == hash) {
106-
off += data_off;
107-
auto pos = fp.tellg();
108-
string key_now;
109-
getstr(key_now, off);
110-
if (key == key_now) {
111-
return off + (unsigned int)key.size() + 1;
112-
}
113-
fp.seekg(pos);
114-
}*/
163+
std::string rva2name(int rva) {
164+
int siz_rva = SIZSEG[SEGMENT_RVA_INT];
165+
char *buf = new char[siz_rva];
166+
ifs.seekg({SEGOFF[SEGMENT_RVA_INT]});
167+
ifs.read(buf, siz_rva);
168+
int *need = (int *)buf;
169+
int *end = need + siz_rva / 4;
170+
int *found = std::find(need, end, rva);
171+
if (found == end) {
172+
return "(nil)";
115173
}
116-
for (auto off : tolookup) {
117-
fp.seekg({off});
118-
if (_cmp(key)) {
119-
return off + (uint32_t)key.size() + 1;
120-
}
174+
int internalId = int(std::distance(need, found));
175+
int soff = _pfread<int>(SEGOFF[SEGMENT_STRINGS_IDX] + internalId * 4);
176+
int slen = _pfread<int>(SEGOFF[SEGMENT_STRINGS_IDX] + internalId * 4 + 4) - soff;
177+
ifs.seekg({int(SEGOFF[SEGMENT_STRINGS] + soff)});
178+
std::string rv;
179+
rv.resize(slen, 0);
180+
ifs.read(rv.data(), slen);
181+
delete[] buf;
182+
return rv;
183+
}
184+
void dumpall(unordered_map<string, int, aphash>* hashMap) {
185+
int siz_rva = SIZSEG[SEGMENT_RVA_INT];
186+
char *buf = new char[siz_rva];
187+
ifs.seekg({SEGOFF[SEGMENT_RVA_INT]});
188+
ifs.read(buf, siz_rva);
189+
int *need = (int *)buf;
190+
int *end = need + siz_rva / 4;
191+
for (int a = 0; need + a != end; a++) {
192+
int *rva = need + a;
193+
int internalId = int(std::distance(need, rva));
194+
int soff = _pfread<int>(SEGOFF[SEGMENT_STRINGS_IDX] + internalId * 4);
195+
int slen = _pfread<int>(SEGOFF[SEGMENT_STRINGS_IDX] + internalId * 4 + 4) - soff;
196+
ifs.seekg({int(SEGOFF[SEGMENT_STRINGS] + soff)});
197+
char *rv = new char[slen];
198+
ifs.read((char *)rv, slen);
199+
hashMap->insert({rv, *rva});
200+
//hashMap[rv] = *rva;
201+
// printf("[%08d] %s\n", *rva, rv.c_str());
202+
delete[] rv;
121203
}
122-
return 0;
204+
205+
delete[] buf;
123206
}
124207
};
125-
static RoDB_R *pdb;
208+
int fnstat = 0;
209+
static SymDBReader *SymDB;
126210
static uintptr_t BaseAdr;
127-
string ptr2name(void *ptr) {
128-
unsigned int va = uint32_t(((uintptr_t)ptr - BaseAdr));
129-
return pdb->val2key(va);
211+
unordered_map<string, int, aphash> *FuncMap;
212+
void InitFastDlsym() {
213+
printf("[Info] Loading Symbols\n");
214+
unordered_map<string, int, aphash> *realFuncMap = new unordered_map<string, int, aphash>;
215+
SymDB->dumpall(realFuncMap);
216+
fnstat = 1;
217+
SymDB = nullptr;
218+
SymDB = new SymDBReader("bedrock_server.symdb2");
219+
FuncMap = realFuncMap;
220+
printf("[Info] FastDlsymInited <%zd>\n", realFuncMap->size());
130221
}
131222
void *dlsym_real(const char *x) {
132-
if (pdb == nullptr) {
133-
if (!std::filesystem::exists("bedrock_server.symdb")) {
134-
printf("SymDB not found\ntry to run RoDB.exe\n");
223+
if (SymDB == nullptr) {
224+
if (!std::filesystem::exists("bedrock_server.symdb2")) {
225+
printf("SymDB not found\ntry to run SymDB2.exe\n");
135226
std::this_thread::sleep_for(std::chrono::seconds(10));
136227
exit(1);
137228
}
138-
pdb = new RoDB_R("bedrock_server.symdb");
229+
SymDB = new SymDBReader("bedrock_server.symdb2");
139230
BaseAdr = (uintptr_t)GetModuleHandle(NULL);
140231
static_assert(sizeof(GetModuleHandle(NULL)) == 8);
141232
}
142-
auto rv = pdb->get(x);
143-
if (!rv)
144-
return nullptr;
145-
unsigned int rva;
146-
pdb->read(&rva, rv, 4);
147-
return (void *)(BaseAdr + rva);
233+
if (fnstat == 0)
234+
InitFastDlsym();
235+
for (;fnstat == 0;) {
236+
std::this_thread::sleep_for(std::chrono::seconds(1));
237+
}
238+
if (fnstat == 1) {
239+
auto iter = FuncMap->find(x);
240+
if (iter != FuncMap->end()) {
241+
//std::cout<<x<<" : "<<iter->second<<" == "<<rv<<std::endl;
242+
return (void *)(BaseAdr + iter->second);
243+
}
244+
}
245+
auto rv = SymDB->getsym(x);
246+
if (!rv)
247+
return nullptr;
248+
return (void *)(BaseAdr + rv);
148249
}
149250
inline static void HookFunction__begin() {
150251
DetourTransactionBegin();

LiteLoader/pch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <api\xuidreg\xuidreg.h>
1818
#include <lbpch.h>
1919
#include <filesystem>
20+
#include <map>
2021
#include "framework.h"
2122
// CheckUpdate.cpp
2223
#include <rapidjson\document.h>

LiteLoader/xuidreg/xuidreg.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void initAll() {
7979
auto _xuid = offPlayer::getXUIDString(sp);
8080
xuid_t xuid;
8181
if (_xuid.size() <= 1)
82-
xuid = do_hash(name);
82+
xuid = do_hash(name.c_str());
8383
else
8484
xuid = std::stoull(_xuid);
8585
insert(xuid, name);

Tool/SymDB2.exe

4.82 MB
Binary file not shown.

0 commit comments

Comments
 (0)