|
fyrenmoo@3129
|
1 |
#include <stdio.h> |
|
fyrenmoo@3129
|
2 |
#include <unistd.h> |
|
fyrenmoo@3129
|
3 |
#include <dlfcn.h> |
|
fyrenmoo@3129
|
4 |
#include <math.h> |
|
fyrenmoo@3129
|
5 |
#include "gdc.h" |
|
fyrenmoo@3129
|
6 |
#include "GameConfigs.h" |
|
fyrenmoo@3129
|
7 |
#include "MemoryUtils.h" |
|
fyrenmoo@3129
|
8 |
|
|
fyrenmoo@3129
|
9 |
MemoryUtils mu; |
|
fyrenmoo@3129
|
10 |
|
|
fyrenmoo@3129
|
11 |
char *game = NULL; |
|
fyrenmoo@3129
|
12 |
char *engine = NULL; |
|
fyrenmoo@3129
|
13 |
char *binary = NULL; |
|
fyrenmoo@3129
|
14 |
|
|
fyrenmoo@3129
|
15 |
int main(int argc, char **argv) |
|
fyrenmoo@3129
|
16 |
{ |
|
fyrenmoo@3129
|
17 |
char *gamedata = NULL; |
|
fyrenmoo@3129
|
18 |
bool debug = false; |
|
fyrenmoo@3129
|
19 |
|
|
fyrenmoo@3129
|
20 |
opterr = 0; |
|
fyrenmoo@3129
|
21 |
int opt; |
|
fyrenmoo@3129
|
22 |
while ((opt = getopt(argc, argv, "b:de:f:g:")) != -1) |
|
fyrenmoo@3129
|
23 |
switch (opt) |
|
fyrenmoo@3129
|
24 |
{ |
|
fyrenmoo@3129
|
25 |
case 'd': |
|
fyrenmoo@3129
|
26 |
debug = true; |
|
fyrenmoo@3129
|
27 |
break; |
|
fyrenmoo@3129
|
28 |
case 'g': |
|
fyrenmoo@3129
|
29 |
game = optarg; |
|
fyrenmoo@3129
|
30 |
break; |
|
fyrenmoo@3129
|
31 |
|
|
fyrenmoo@3129
|
32 |
case 'e': |
|
fyrenmoo@3129
|
33 |
engine = optarg; |
|
fyrenmoo@3129
|
34 |
break; |
|
fyrenmoo@3129
|
35 |
|
|
fyrenmoo@3129
|
36 |
case 'f': |
|
fyrenmoo@3129
|
37 |
gamedata = optarg; |
|
fyrenmoo@3129
|
38 |
break; |
|
fyrenmoo@3129
|
39 |
|
|
fyrenmoo@3129
|
40 |
case 'b': |
|
fyrenmoo@3129
|
41 |
binary = optarg; |
|
fyrenmoo@3129
|
42 |
break; |
|
fyrenmoo@3129
|
43 |
|
|
fyrenmoo@3129
|
44 |
case '?': |
|
fyrenmoo@3129
|
45 |
printf("Usage: ./gdc -g <game> -e <engine> -f <gamedata file> -b <binary>\n"); |
|
fyrenmoo@3129
|
46 |
return 0; |
|
fyrenmoo@3129
|
47 |
|
|
fyrenmoo@3129
|
48 |
default: |
|
fyrenmoo@3129
|
49 |
printf("WHAT\n"); |
|
fyrenmoo@3129
|
50 |
return 0; |
|
fyrenmoo@3129
|
51 |
} |
|
fyrenmoo@3129
|
52 |
|
|
fyrenmoo@3129
|
53 |
if (!game || !engine || !gamedata || !binary) |
|
fyrenmoo@3129
|
54 |
{ |
|
fyrenmoo@3129
|
55 |
printf("Usage: ./gdc -g <game> -e <engine> -f <gamedata file> -b <binary>\n"); |
|
fyrenmoo@3129
|
56 |
return 0; |
|
fyrenmoo@3129
|
57 |
} |
|
fyrenmoo@3129
|
58 |
|
|
fyrenmoo@3129
|
59 |
printf("Game: %s\nEngine: %s\nGamedata: %s\nBinary: %s\n", game, engine, gamedata, binary); |
|
fyrenmoo@3129
|
60 |
|
|
fyrenmoo@3129
|
61 |
void *handle = dlopen(binary, RTLD_LAZY); |
|
fyrenmoo@3129
|
62 |
if (!handle) |
|
fyrenmoo@3129
|
63 |
{ |
|
fyrenmoo@3129
|
64 |
printf("Couldn't open %s (%s)\n", binary, dlerror()); |
|
fyrenmoo@3129
|
65 |
return 0; |
|
fyrenmoo@3129
|
66 |
} |
|
fyrenmoo@3129
|
67 |
|
|
fyrenmoo@3129
|
68 |
CGameConfig gc; |
|
fyrenmoo@3129
|
69 |
char err[512]; |
|
fyrenmoo@3129
|
70 |
if (!gc.EnterFile(gamedata, err, sizeof(err))) |
|
fyrenmoo@3129
|
71 |
{ |
|
fyrenmoo@3129
|
72 |
printf("%s: %s\n", gamedata, err); |
|
fyrenmoo@3129
|
73 |
return 0; |
|
fyrenmoo@3129
|
74 |
} |
|
fyrenmoo@3129
|
75 |
|
|
fyrenmoo@3129
|
76 |
CGameConfig symbols; |
|
fyrenmoo@3129
|
77 |
if (!symbols.EnterFile("symbols.txt", err, sizeof(err))) |
|
fyrenmoo@3129
|
78 |
{ |
|
fyrenmoo@3129
|
79 |
printf("symbols.txt: %s\n", err); |
|
fyrenmoo@3129
|
80 |
return 0; |
|
fyrenmoo@3129
|
81 |
} |
|
fyrenmoo@3129
|
82 |
|
|
fyrenmoo@3129
|
83 |
if (debug) |
|
fyrenmoo@3129
|
84 |
for (map<const char*, const char*, cmp_str>::iterator it = symbols.m_Keys.begin(); it != symbols.m_Keys.end(); it++) |
|
fyrenmoo@3129
|
85 |
printf("%s - %s\n", it->first, it->second); |
|
fyrenmoo@3129
|
86 |
|
|
fyrenmoo@3129
|
87 |
const char *vtsym = symbols.GetKeyValue("vtsym"); |
|
fyrenmoo@3129
|
88 |
if (!vtsym) |
|
fyrenmoo@3129
|
89 |
{ |
|
fyrenmoo@3129
|
90 |
printf("Couldn't find vtsym\n"); |
|
fyrenmoo@3129
|
91 |
return 0; |
|
fyrenmoo@3129
|
92 |
} |
|
fyrenmoo@3129
|
93 |
|
|
fyrenmoo@3129
|
94 |
#if 0 |
|
fyrenmoo@3129
|
95 |
void *lolwhat = (void*)1; |
|
fyrenmoo@3129
|
96 |
void *handle = lolwhat; |
|
fyrenmoo@3129
|
97 |
handle = dlopen(binary, RTLD_LAZY); |
|
fyrenmoo@3129
|
98 |
if (!handle) |
|
fyrenmoo@3129
|
99 |
{ |
|
fyrenmoo@3129
|
100 |
printf("Couldn't open %s\n", binary); |
|
fyrenmoo@3129
|
101 |
return 0; |
|
fyrenmoo@3129
|
102 |
} |
|
fyrenmoo@3129
|
103 |
#endif |
|
fyrenmoo@3129
|
104 |
|
|
fyrenmoo@3129
|
105 |
void **vt = (void**) mu.ResolveSymbol(handle, vtsym); |
|
fyrenmoo@3129
|
106 |
if (!vt) |
|
fyrenmoo@3129
|
107 |
{ |
|
fyrenmoo@3129
|
108 |
printf("Couldn't find vtable %s\n", vtsym); |
|
fyrenmoo@3129
|
109 |
dlclose(handle); |
|
fyrenmoo@3129
|
110 |
return 0; |
|
fyrenmoo@3129
|
111 |
} |
|
fyrenmoo@3129
|
112 |
|
|
fyrenmoo@3129
|
113 |
|
|
fyrenmoo@3129
|
114 |
for (list<Offset>::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++) |
|
fyrenmoo@3129
|
115 |
{ |
|
fyrenmoo@3129
|
116 |
if (debug) printf("DEBUG %s - l: %d w: %d\n", it->name, it->lin, it->win); |
|
fyrenmoo@3129
|
117 |
// else |
|
fyrenmoo@3129
|
118 |
{ |
|
fyrenmoo@3129
|
119 |
const char *symbol = symbols.GetKeyValue(it->name); |
|
fyrenmoo@3129
|
120 |
if (symbol) |
|
fyrenmoo@3129
|
121 |
{ |
|
fyrenmoo@3129
|
122 |
int offset = findVFunc(handle, vt, symbol); |
|
fyrenmoo@3129
|
123 |
|
|
fyrenmoo@3129
|
124 |
if (offset == it->lin) printf("%s - good\n", it->name); |
|
fyrenmoo@3129
|
125 |
else printf("%s - l: %d w: %d\n", it->name, offset, offset + it->lin - it->win); |
|
fyrenmoo@3129
|
126 |
} |
|
fyrenmoo@3129
|
127 |
else printf("%s - no Linux symbol, skipping\n", it->name); |
|
fyrenmoo@3129
|
128 |
} |
|
fyrenmoo@3129
|
129 |
} |
|
fyrenmoo@3129
|
130 |
|
|
fyrenmoo@3129
|
131 |
printf("\nWindows offsets are wild guesses!\n\n"); |
|
fyrenmoo@3129
|
132 |
|
|
fyrenmoo@3129
|
133 |
for (list<Sig>::iterator it = gc.m_Sigs.begin(); it != gc.m_Sigs.end(); it++) |
|
fyrenmoo@3129
|
134 |
{ |
|
fyrenmoo@3129
|
135 |
if (debug) printf("DEBUG %s - %s - l: %s\n", it->name, it->lib == Server ? "server" : "engine", it->lin); |
|
fyrenmoo@3129
|
136 |
// else |
|
fyrenmoo@3129
|
137 |
{ |
|
fyrenmoo@3129
|
138 |
if (it->lib != Server) |
|
fyrenmoo@3129
|
139 |
{ |
|
fyrenmoo@3129
|
140 |
printf("%s - isn't server, skipping\n", it->name); |
|
fyrenmoo@3129
|
141 |
continue; |
|
fyrenmoo@3129
|
142 |
} |
|
fyrenmoo@3129
|
143 |
|
|
fyrenmoo@3129
|
144 |
const char *symbol = it->lin; |
|
fyrenmoo@3129
|
145 |
|
|
fyrenmoo@3129
|
146 |
if (!symbol) |
|
fyrenmoo@3129
|
147 |
{ |
|
fyrenmoo@3129
|
148 |
printf("%s - no Linux symbol, skipping\n", it->name); |
|
fyrenmoo@3129
|
149 |
continue; |
|
fyrenmoo@3129
|
150 |
} |
|
fyrenmoo@3129
|
151 |
|
|
fyrenmoo@3129
|
152 |
if (symbol[0] != '@') |
|
fyrenmoo@3129
|
153 |
{ |
|
fyrenmoo@3129
|
154 |
printf("%s - didn't start with '@', skipping\n", it->name); |
|
fyrenmoo@3129
|
155 |
continue; |
|
fyrenmoo@3129
|
156 |
} |
|
fyrenmoo@3129
|
157 |
|
|
fyrenmoo@3129
|
158 |
void *addr = mu.ResolveSymbol(handle, symbol + 1); |
|
fyrenmoo@3129
|
159 |
|
|
fyrenmoo@3129
|
160 |
if (addr) printf("%s - good\n", it->name); |
|
fyrenmoo@3129
|
161 |
else printf("%s - %s not found\n", it->name, it->lin); |
|
fyrenmoo@3129
|
162 |
} |
|
fyrenmoo@3129
|
163 |
} |
|
fyrenmoo@3129
|
164 |
|
|
fyrenmoo@3129
|
165 |
return 0; |
|
fyrenmoo@3129
|
166 |
} |
|
fyrenmoo@3129
|
167 |
|
|
fyrenmoo@3129
|
168 |
/* |
|
fyrenmoo@3129
|
169 |
takes a mangled member function symbol and returns the position where the function name and parameters start |
|
fyrenmoo@3129
|
170 |
01234567890123456789012345678 |
|
fyrenmoo@3129
|
171 |
_ZN9CTFPlayer12ForceRespawnEv |
|
fyrenmoo@3129
|
172 |
^13 ^28 |
|
fyrenmoo@3129
|
173 |
*/ |
|
fyrenmoo@3129
|
174 |
void findFuncPos(const char *sym, int &func, int ¶ms) |
|
fyrenmoo@3129
|
175 |
{ |
|
fyrenmoo@3129
|
176 |
int i = 0; |
|
fyrenmoo@3129
|
177 |
while ((sym[i] < '0') || (sym[i] > '9')) i++; |
|
fyrenmoo@3129
|
178 |
int classLen = atoi(sym + i); |
|
fyrenmoo@3129
|
179 |
func = i + (int)ceil(log10(classLen)) + classLen; |
|
fyrenmoo@3129
|
180 |
int funcLen = atoi(sym + func); |
|
fyrenmoo@3129
|
181 |
params = func + (int)ceil(log10(funcLen)) + funcLen; |
|
fyrenmoo@3129
|
182 |
} |
|
fyrenmoo@3129
|
183 |
|
|
fyrenmoo@3129
|
184 |
int findVFunc(void *handle, void **vt, const char *symbol) |
|
fyrenmoo@3129
|
185 |
{ |
|
fyrenmoo@3129
|
186 |
int offset = 1; |
|
fyrenmoo@3129
|
187 |
//int overloads = 0; |
|
fyrenmoo@3129
|
188 |
int funcPos, paramPos; |
|
fyrenmoo@3129
|
189 |
findFuncPos(symbol, funcPos, paramPos); |
|
fyrenmoo@3129
|
190 |
|
|
fyrenmoo@3129
|
191 |
for (int i = 0; i < 1000; i++) |
|
fyrenmoo@3129
|
192 |
{ |
|
fyrenmoo@3129
|
193 |
void *pFunc = vt[i]; |
|
fyrenmoo@3129
|
194 |
const char *s; |
|
fyrenmoo@3129
|
195 |
|
|
fyrenmoo@3129
|
196 |
// Dl_info info; |
|
fyrenmoo@3129
|
197 |
// if (!mu.ResolveAddr(pFunc, &info)) continue; |
|
fyrenmoo@3129
|
198 |
if (!(s = mu.ResolveAddr(handle, pFunc))) continue; |
|
fyrenmoo@3129
|
199 |
|
|
fyrenmoo@3129
|
200 |
// if ((i > 1) && (strncmp(info.dli_sname, "_ZTI", 4) == 0)) break; |
|
fyrenmoo@3129
|
201 |
if ((i > 1) && (strncmp(s, "_ZTI", 4) == 0)) break; |
|
fyrenmoo@3129
|
202 |
|
|
fyrenmoo@3129
|
203 |
|
|
fyrenmoo@3129
|
204 |
int tempFuncPos, tempParamPos; |
|
fyrenmoo@3129
|
205 |
// findFuncPos(info.dli_sname, tempFuncPos, tempParamPos); |
|
fyrenmoo@3129
|
206 |
findFuncPos(s, tempFuncPos, tempParamPos); |
|
fyrenmoo@3129
|
207 |
|
|
fyrenmoo@3129
|
208 |
#if 0 |
|
fyrenmoo@3129
|
209 |
if (strncmp(info.dli_sname[tempFuncPos], symbol[funcPos], paramPos - funcPos) == 0) |
|
fyrenmoo@3129
|
210 |
{ |
|
fyrenmoo@3129
|
211 |
overloads++; |
|
fyrenmoo@3129
|
212 |
if (firstOverload == -1) firstOverload = i - 1; |
|
fyrenmoo@3129
|
213 |
if (strncmp(info.dli_sname[tempParamPos], symbol[paramPos], strlen(symbol) - paramPos) == 0) |
|
fyrenmoo@3129
|
214 |
{ |
|
fyrenmoo@3129
|
215 |
offset = i; |
|
fyrenmoo@3129
|
216 |
matchingOverload = overloads; |
|
fyrenmoo@3129
|
217 |
} |
|
fyrenmoo@3129
|
218 |
} |
|
fyrenmoo@3129
|
219 |
#else |
|
fyrenmoo@3129
|
220 |
// if (strcmp(info.dli_sname + tempFuncPos, symbol + funcPos) == 0) |
|
fyrenmoo@3129
|
221 |
if (strcmp(s + tempFuncPos, symbol + funcPos) == 0) |
|
fyrenmoo@3129
|
222 |
{ |
|
fyrenmoo@3129
|
223 |
offset = i; |
|
fyrenmoo@3129
|
224 |
break; |
|
fyrenmoo@3129
|
225 |
} |
|
fyrenmoo@3129
|
226 |
#endif |
|
fyrenmoo@3129
|
227 |
} |
|
fyrenmoo@3129
|
228 |
|
|
fyrenmoo@3129
|
229 |
return offset - 2; |
|
fyrenmoo@3129
|
230 |
} |
|
fyrenmoo@3129
|
231 |
|
|
fyrenmoo@3129
|
232 |
unsigned int strncopy(char *dest, const char *src, size_t count) |
|
fyrenmoo@3129
|
233 |
{ |
|
fyrenmoo@3129
|
234 |
if (!count) |
|
fyrenmoo@3129
|
235 |
{ |
|
fyrenmoo@3129
|
236 |
return 0; |
|
fyrenmoo@3129
|
237 |
} |
|
fyrenmoo@3129
|
238 |
|
|
fyrenmoo@3129
|
239 |
char *start = dest; |
|
fyrenmoo@3129
|
240 |
while ((*src) && (--count)) |
|
fyrenmoo@3129
|
241 |
{ |
|
fyrenmoo@3129
|
242 |
*dest++ = *src++; |
|
fyrenmoo@3129
|
243 |
} |
|
fyrenmoo@3129
|
244 |
*dest = '\0'; |
|
fyrenmoo@3129
|
245 |
|
|
fyrenmoo@3129
|
246 |
return (dest - start); |
|
fyrenmoo@3129
|
247 |
} |
|
fyrenmoo@3129
|
248 |
|
|
fyrenmoo@3129
|
249 |
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) |
|
fyrenmoo@3129
|
250 |
{ |
|
fyrenmoo@3129
|
251 |
va_list ap; |
|
fyrenmoo@3129
|
252 |
va_start(ap, fmt); |
|
fyrenmoo@3129
|
253 |
size_t len = vsnprintf(buffer, maxlength, fmt, ap); |
|
fyrenmoo@3129
|
254 |
va_end(ap); |
|
fyrenmoo@3129
|
255 |
|
|
fyrenmoo@3129
|
256 |
if (len >= maxlength) |
|
fyrenmoo@3129
|
257 |
{ |
|
fyrenmoo@3129
|
258 |
buffer[maxlength - 1] = '\0'; |
|
fyrenmoo@3129
|
259 |
return (maxlength - 1); |
|
fyrenmoo@3129
|
260 |
} |
|
fyrenmoo@3129
|
261 |
else |
|
fyrenmoo@3129
|
262 |
{ |
|
fyrenmoo@3129
|
263 |
return len; |
|
fyrenmoo@3129
|
264 |
} |
|
fyrenmoo@3129
|
265 |
} |
|
fyrenmoo@3129
|
266 |
|