|
skamonkey@3513
|
1 |
#include <stdio.h> |
|
skamonkey@3513
|
2 |
#include <unistd.h> |
|
skamonkey@3513
|
3 |
#include <dlfcn.h> |
|
skamonkey@3513
|
4 |
#include <fcntl.h> |
|
skamonkey@3513
|
5 |
#include <math.h> |
|
skamonkey@3574
|
6 |
#include <iostream> |
|
skamonkey@3513
|
7 |
#include "gdc.h" |
|
skamonkey@3513
|
8 |
#include "GameConfigs.h" |
|
skamonkey@3513
|
9 |
#include "MemoryUtils.h" |
|
skamonkey@3513
|
10 |
|
|
skamonkey@3513
|
11 |
MemoryUtils mu; |
|
skamonkey@3513
|
12 |
|
|
skamonkey@3513
|
13 |
char *game = NULL; |
|
skamonkey@3513
|
14 |
char *engine = NULL; |
|
skamonkey@3513
|
15 |
char *game_binary = NULL; |
|
skamonkey@3513
|
16 |
char *engine_binary = NULL; |
|
skamonkey@3513
|
17 |
char *wgame_binary = NULL; |
|
skamonkey@3513
|
18 |
char *wengine_binary = NULL; |
|
skamonkey@3742
|
19 |
char *symbols_file = NULL; |
|
skamonkey@3742
|
20 |
|
|
skamonkey@3742
|
21 |
bool use_symtab = true; |
|
Dr!fter@3954
|
22 |
CGameConfig symbols; |
|
Dr!fter@3954
|
23 |
CGameConfig gc; |
|
skamonkey@3513
|
24 |
|
|
skamonkey@3574
|
25 |
inline bool IsDigit( char c ) |
|
skamonkey@3574
|
26 |
{ |
|
skamonkey@3574
|
27 |
return c < 58 && c > 47; |
|
skamonkey@3574
|
28 |
} |
|
skamonkey@3574
|
29 |
|
|
skamonkey@3742
|
30 |
void PrintUsage() |
|
skamonkey@3742
|
31 |
{ |
|
skamonkey@3742
|
32 |
printf("Usage: ./gdc -g <game> -e <engine name> -f <gamedata file> -b <game binary> -x <engine binary> -w <win game binary> -y <win engine binary> [-s <symbols.txt file>]\n"); |
|
skamonkey@3742
|
33 |
printf("Other options:\n"); |
|
skamonkey@3742
|
34 |
printf(" -d\tAdd debug output\n"); |
|
skamonkey@3742
|
35 |
printf(" -n\tDon't use symbol table for lookups (falls back to dlsym)\n"); |
|
skamonkey@3742
|
36 |
} |
|
skamonkey@3742
|
37 |
|
|
skamonkey@3513
|
38 |
int main(int argc, char **argv) |
|
skamonkey@3513
|
39 |
{ |
|
skamonkey@3513
|
40 |
char *gamedata = NULL; |
|
skamonkey@3513
|
41 |
bool debug = false; |
|
skamonkey@3513
|
42 |
|
|
skamonkey@3513
|
43 |
opterr = 0; |
|
skamonkey@3513
|
44 |
int opt; |
|
skamonkey@3742
|
45 |
while ((opt = getopt(argc, argv, "b:nde:f:g:x:w:y:s:")) != -1) |
|
skamonkey@3742
|
46 |
{ |
|
skamonkey@3513
|
47 |
switch (opt) |
|
skamonkey@3513
|
48 |
{ |
|
skamonkey@3513
|
49 |
case 'd': |
|
skamonkey@3513
|
50 |
debug = true; |
|
skamonkey@3513
|
51 |
break; |
|
skamonkey@3742
|
52 |
|
|
skamonkey@3742
|
53 |
case 'n': |
|
skamonkey@3742
|
54 |
use_symtab = false; |
|
skamonkey@3742
|
55 |
break; |
|
skamonkey@3742
|
56 |
|
|
skamonkey@3513
|
57 |
case 'g': |
|
skamonkey@3513
|
58 |
game = optarg; |
|
skamonkey@3513
|
59 |
break; |
|
skamonkey@3513
|
60 |
|
|
skamonkey@3513
|
61 |
case 'e': |
|
skamonkey@3513
|
62 |
engine = optarg; |
|
skamonkey@3513
|
63 |
break; |
|
skamonkey@3513
|
64 |
|
|
skamonkey@3513
|
65 |
case 'f': |
|
skamonkey@3513
|
66 |
gamedata = optarg; |
|
skamonkey@3513
|
67 |
break; |
|
skamonkey@3513
|
68 |
|
|
skamonkey@3513
|
69 |
case 'b': |
|
skamonkey@3513
|
70 |
game_binary = optarg; |
|
skamonkey@3513
|
71 |
break; |
|
skamonkey@3513
|
72 |
|
|
skamonkey@3513
|
73 |
case 'x': |
|
skamonkey@3513
|
74 |
engine_binary = optarg; |
|
skamonkey@3513
|
75 |
break; |
|
skamonkey@3513
|
76 |
|
|
skamonkey@3513
|
77 |
case 'w': |
|
skamonkey@3513
|
78 |
wgame_binary = optarg; |
|
skamonkey@3513
|
79 |
break; |
|
skamonkey@3513
|
80 |
|
|
skamonkey@3513
|
81 |
case 'y': |
|
skamonkey@3513
|
82 |
wengine_binary = optarg; |
|
skamonkey@3513
|
83 |
break; |
|
skamonkey@3513
|
84 |
|
|
skamonkey@3742
|
85 |
case 's': |
|
skamonkey@3742
|
86 |
symbols_file = optarg; |
|
skamonkey@3742
|
87 |
break; |
|
skamonkey@3742
|
88 |
|
|
skamonkey@3513
|
89 |
case '?': |
|
skamonkey@3742
|
90 |
PrintUsage(); |
|
skamonkey@3513
|
91 |
return 0; |
|
skamonkey@3513
|
92 |
|
|
skamonkey@3513
|
93 |
default: |
|
skamonkey@3513
|
94 |
printf("WHAT\n"); |
|
skamonkey@3513
|
95 |
return 0; |
|
skamonkey@3513
|
96 |
} |
|
skamonkey@3742
|
97 |
} |
|
skamonkey@3513
|
98 |
|
|
skamonkey@3513
|
99 |
if (!game || !engine || !gamedata || !game_binary || !engine_binary || !wgame_binary || !wengine_binary) |
|
skamonkey@3513
|
100 |
{ |
|
skamonkey@3742
|
101 |
PrintUsage(); |
|
skamonkey@3513
|
102 |
return 0; |
|
skamonkey@3513
|
103 |
} |
|
skamonkey@3513
|
104 |
|
|
skamonkey@3513
|
105 |
printf("Game: %s\n", game); |
|
skamonkey@3513
|
106 |
if (debug) |
|
skamonkey@3513
|
107 |
{ |
|
skamonkey@3513
|
108 |
printf("Engine: %s\nGame binary: %s\nEngine binary: %s\nWin game binary: %s\nWin engine binary: %s\n", |
|
skamonkey@3513
|
109 |
engine, game_binary, engine_binary, wgame_binary, wengine_binary |
|
skamonkey@3513
|
110 |
); |
|
skamonkey@3513
|
111 |
} |
|
skamonkey@3513
|
112 |
printf("Gamedata: %s\n\n", gamedata); |
|
skamonkey@3513
|
113 |
|
|
skamonkey@3513
|
114 |
void *ghandle; |
|
skamonkey@3513
|
115 |
ghandle = dlopen(game_binary, RTLD_LAZY); |
|
skamonkey@3513
|
116 |
if (!ghandle) |
|
skamonkey@3513
|
117 |
{ |
|
skamonkey@3513
|
118 |
printf("Couldn't open %s (%s)\n", game_binary, dlerror()); |
|
skamonkey@3513
|
119 |
return 0; |
|
skamonkey@3513
|
120 |
} |
|
skamonkey@3513
|
121 |
void *ehandle; |
|
skamonkey@3513
|
122 |
ehandle = dlopen(engine_binary, RTLD_LAZY); |
|
skamonkey@3513
|
123 |
if (!ehandle) |
|
skamonkey@3513
|
124 |
{ |
|
skamonkey@3513
|
125 |
printf("Couldn't open %s (%s)\n", engine_binary, dlerror()); |
|
skamonkey@3513
|
126 |
return 0; |
|
skamonkey@3513
|
127 |
} |
|
skamonkey@3513
|
128 |
|
|
skamonkey@3513
|
129 |
int wgfile = open(wgame_binary, O_RDONLY); |
|
skamonkey@3513
|
130 |
if (wgfile == -1) |
|
skamonkey@3513
|
131 |
{ |
|
skamonkey@3513
|
132 |
printf("Couldn't open %s\n", wgame_binary); |
|
skamonkey@3513
|
133 |
return 0; |
|
skamonkey@3513
|
134 |
} |
|
skamonkey@3513
|
135 |
|
|
skamonkey@3513
|
136 |
int wefile = open(wengine_binary, O_RDONLY); |
|
skamonkey@3513
|
137 |
if (wefile == -1) |
|
skamonkey@3513
|
138 |
{ |
|
skamonkey@3513
|
139 |
printf("Couldn't open %s\n", wengine_binary); |
|
skamonkey@3513
|
140 |
return 0; |
|
skamonkey@3513
|
141 |
} |
|
skamonkey@3513
|
142 |
|
|
skamonkey@3513
|
143 |
char err[512]; |
|
skamonkey@3513
|
144 |
if (!gc.EnterFile(gamedata, err, sizeof(err))) |
|
skamonkey@3513
|
145 |
{ |
|
skamonkey@3513
|
146 |
printf("%s: %s\n", gamedata, err); |
|
skamonkey@3513
|
147 |
return 0; |
|
skamonkey@3513
|
148 |
} |
|
skamonkey@3513
|
149 |
|
|
skamonkey@3742
|
150 |
if (!symbols.EnterFile(symbols_file ? symbols_file : "symbols.txt", err, sizeof(err))) |
|
skamonkey@3513
|
151 |
{ |
|
skamonkey@3513
|
152 |
printf("symbols.txt: %s\n", err); |
|
skamonkey@3513
|
153 |
return 0; |
|
skamonkey@3513
|
154 |
} |
|
skamonkey@3513
|
155 |
|
|
skamonkey@3513
|
156 |
for (list<Offset>::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++) |
|
skamonkey@3513
|
157 |
{ |
|
skamonkey@3513
|
158 |
if (debug) |
|
skamonkey@3513
|
159 |
{ |
|
skamonkey@3513
|
160 |
printf("DEBUG %s - l: %d w: %d\n", it->name, it->lin, it->win); |
|
skamonkey@3513
|
161 |
} |
|
skamonkey@3513
|
162 |
|
|
skamonkey@3513
|
163 |
const char *symbol = symbols.GetKeyValue(it->name); |
|
skamonkey@3513
|
164 |
if (symbol) |
|
skamonkey@3513
|
165 |
{ |
|
skamonkey@3574
|
166 |
char symvt[128] = "_ZTV"; |
|
skamonkey@3574
|
167 |
bool bGotFirstNumbers = false; |
|
skamonkey@3574
|
168 |
bool bLastNumberDigit = false; |
|
skamonkey@3574
|
169 |
unsigned int symlen = strlen(symbol); |
|
skamonkey@3574
|
170 |
unsigned int pos = strlen(symvt); |
|
skamonkey@3574
|
171 |
|
|
skamonkey@3574
|
172 |
for ( unsigned int i = 0; i < symlen && pos < (sizeof(symvt)-1); ++i ) |
|
skamonkey@3574
|
173 |
{ |
|
skamonkey@3574
|
174 |
bool isDigit = IsDigit( symbol[i] ); |
|
skamonkey@3574
|
175 |
if( !isDigit && bLastNumberDigit ) |
|
skamonkey@3574
|
176 |
{ |
|
skamonkey@3574
|
177 |
bGotFirstNumbers = true; |
|
skamonkey@3574
|
178 |
} |
|
skamonkey@3574
|
179 |
|
|
skamonkey@3574
|
180 |
// we're before the class len |
|
skamonkey@3574
|
181 |
if( !bGotFirstNumbers && !isDigit ) |
|
skamonkey@3574
|
182 |
continue; |
|
skamonkey@3574
|
183 |
|
|
skamonkey@3574
|
184 |
// we're at the function name len |
|
skamonkey@3574
|
185 |
if( bGotFirstNumbers && isDigit ) |
|
skamonkey@3574
|
186 |
{ |
|
skamonkey@3574
|
187 |
symvt[pos] = 0; |
|
skamonkey@3574
|
188 |
break; |
|
skamonkey@3574
|
189 |
} |
|
skamonkey@3574
|
190 |
|
|
skamonkey@3574
|
191 |
// we're at the class len or class name. we want these |
|
skamonkey@3574
|
192 |
symvt[pos++] = symbol[i]; |
|
skamonkey@3574
|
193 |
if( isDigit ) |
|
skamonkey@3574
|
194 |
{ |
|
skamonkey@3574
|
195 |
bLastNumberDigit = isDigit; |
|
skamonkey@3574
|
196 |
} |
|
skamonkey@3574
|
197 |
} |
|
skamonkey@3574
|
198 |
symvt[pos] = 0; |
|
skamonkey@3574
|
199 |
|
|
skamonkey@3513
|
200 |
int newOffset; |
|
skamonkey@3574
|
201 |
if (symvt[0]) |
|
skamonkey@3513
|
202 |
{ |
|
skamonkey@3742
|
203 |
void **newvt = NULL; |
|
skamonkey@3742
|
204 |
if( use_symtab ) |
|
skamonkey@3742
|
205 |
{ |
|
skamonkey@3742
|
206 |
newvt = (void**)mu.ResolveSymbol(ghandle, symvt); |
|
skamonkey@3742
|
207 |
} |
|
skamonkey@3742
|
208 |
else |
|
skamonkey@3742
|
209 |
{ |
|
skamonkey@3742
|
210 |
newvt = (void **)dlsym(ghandle, symvt); |
|
skamonkey@3742
|
211 |
} |
|
skamonkey@3742
|
212 |
|
|
skamonkey@3742
|
213 |
if (!newvt) |
|
skamonkey@3513
|
214 |
{ |
|
skamonkey@3574
|
215 |
printf("? O: %-22s - can't find, skipping\n", symvt); |
|
skamonkey@3513
|
216 |
continue; |
|
skamonkey@3513
|
217 |
} |
|
skamonkey@3513
|
218 |
|
|
skamonkey@3513
|
219 |
newOffset = findVFunc(ghandle, newvt, symbol); |
|
skamonkey@3513
|
220 |
} |
|
skamonkey@3513
|
221 |
|
|
skamonkey@3513
|
222 |
if (newOffset == it->lin) |
|
skamonkey@3513
|
223 |
{ |
|
skamonkey@3574
|
224 |
printf(" O: %-22s - GOOD. current [ w: %3d, l: %3d ].\n", it->name, it->win, it->lin); |
|
skamonkey@3513
|
225 |
} |
|
skamonkey@3513
|
226 |
else |
|
skamonkey@3513
|
227 |
{ |
|
skamonkey@3574
|
228 |
printf("! O: %-22s - CHANGED. old [ w: %3d, l: %3d ]. new [ w: %3d, l: %3d ].\n", |
|
skamonkey@3513
|
229 |
it->name, |
|
skamonkey@3513
|
230 |
it->win, it->lin, |
|
skamonkey@3513
|
231 |
newOffset - (it->lin - it->win), newOffset |
|
skamonkey@3513
|
232 |
); |
|
skamonkey@3513
|
233 |
} |
|
skamonkey@3513
|
234 |
} |
|
skamonkey@3513
|
235 |
else // !symbol |
|
skamonkey@3513
|
236 |
{ |
|
skamonkey@3574
|
237 |
printf(" O: %-22s - no Linux symbol, skipping\n", it->name); |
|
skamonkey@3513
|
238 |
} |
|
skamonkey@3513
|
239 |
} |
|
skamonkey@3513
|
240 |
|
|
Dr!fter@3954
|
241 |
printf("\nWindows offsets are (semi-)wild guesses!\n\nSignature offsets are wild guesses!\n\n"); |
|
skamonkey@3513
|
242 |
|
|
skamonkey@3513
|
243 |
for (list<Sig>::iterator it = gc.m_Sigs.begin(); it != gc.m_Sigs.end(); it++) |
|
skamonkey@3513
|
244 |
{ |
|
skamonkey@3513
|
245 |
if (debug) |
|
skamonkey@3513
|
246 |
{ |
|
skamonkey@3513
|
247 |
printf("DEBUG %s - %s - l: %s\n", it->name, it->lib == Server ? "server" : "engine", it->lin); |
|
skamonkey@3513
|
248 |
} |
|
skamonkey@3513
|
249 |
|
|
skamonkey@3513
|
250 |
const char *linSymbol = it->lin; |
|
skamonkey@3513
|
251 |
const char *winSymbol = it->win; |
|
skamonkey@3513
|
252 |
bool hasLinux = (linSymbol && linSymbol[0]); |
|
skamonkey@3513
|
253 |
bool hasWindows = (winSymbol && winSymbol[0]); |
|
skamonkey@3513
|
254 |
if (!hasLinux && !hasWindows) |
|
skamonkey@3513
|
255 |
{ |
|
skamonkey@3574
|
256 |
printf(" S: %-22s - hasn't linux nor windows data, skipping\n", it->name); |
|
skamonkey@3513
|
257 |
continue; |
|
skamonkey@3513
|
258 |
} |
|
skamonkey@3513
|
259 |
|
|
skamonkey@3513
|
260 |
int winFile; |
|
skamonkey@3513
|
261 |
void *linHandle; |
|
skamonkey@3513
|
262 |
if (it->lib == Server) |
|
skamonkey@3513
|
263 |
{ |
|
skamonkey@3513
|
264 |
winFile = wgfile; |
|
skamonkey@3513
|
265 |
linHandle = ghandle; |
|
skamonkey@3513
|
266 |
} |
|
skamonkey@3513
|
267 |
else if (it->lib == Engine) |
|
skamonkey@3513
|
268 |
{ |
|
skamonkey@3513
|
269 |
winFile = wefile; |
|
skamonkey@3513
|
270 |
linHandle = ehandle; |
|
skamonkey@3513
|
271 |
} |
|
skamonkey@3513
|
272 |
else |
|
skamonkey@3513
|
273 |
{ |
|
skamonkey@3574
|
274 |
printf(" S: %-22s - isn't from server nor engine, skipping\n", it->name); |
|
skamonkey@3513
|
275 |
continue; |
|
skamonkey@3513
|
276 |
} |
|
skamonkey@3513
|
277 |
|
|
skamonkey@3574
|
278 |
int linuxMatches = 0, windowsMatches = 0; |
|
skamonkey@3574
|
279 |
if( hasLinux ) |
|
skamonkey@3574
|
280 |
linuxMatches = checkSigStringL(linHandle, linSymbol); |
|
skamonkey@3574
|
281 |
if( hasWindows ) |
|
skamonkey@3574
|
282 |
windowsMatches = checkSigStringW(winFile, winSymbol); |
|
skamonkey@3513
|
283 |
|
|
skamonkey@3574
|
284 |
if (linuxMatches == 1 && windowsMatches == 1) |
|
skamonkey@3513
|
285 |
{ |
|
skamonkey@3513
|
286 |
// too much clutter to print current data if it matches anyway, unlike with offsets |
|
skamonkey@3513
|
287 |
/* |
|
skamonkey@3513
|
288 |
printf("%-22s (%s) - GOOD. current:\n\t[w:%s]\n\t[l:%s]\n", |
|
skamonkey@3513
|
289 |
it->name, |
|
skamonkey@3513
|
290 |
(it->lib == Server) ? "server" : "engine", |
|
skamonkey@3513
|
291 |
winSymbol ? winSymbol : "", |
|
skamonkey@3513
|
292 |
linSymbol ? linSymbol : "" |
|
skamonkey@3513
|
293 |
); |
|
skamonkey@3513
|
294 |
*/ |
|
skamonkey@3574
|
295 |
printf(" S: %-22s (%s) - w: GOOD - l: GOOD \n", |
|
skamonkey@3513
|
296 |
it->name, |
|
skamonkey@3513
|
297 |
(it->lib == Server) ? "server" : "engine" |
|
skamonkey@3513
|
298 |
); |
|
Dr!fter@3954
|
299 |
|
|
Dr!fter@3954
|
300 |
//Check if they signature has a matching offset |
|
Dr!fter@3954
|
301 |
CheckWindowsSigOffset(it->name, winSymbol, winFile); |
|
Dr!fter@3954
|
302 |
CheckLinuxSigOffset(it->name, linSymbol, linHandle); |
|
Dr!fter@3954
|
303 |
|
|
skamonkey@3513
|
304 |
} |
|
skamonkey@3513
|
305 |
else |
|
skamonkey@3513
|
306 |
{ |
|
skamonkey@3574
|
307 |
char winStatus[16]; |
|
skamonkey@3574
|
308 |
// right now the only option is to ignore |
|
skamonkey@3574
|
309 |
const char *options = symbols.GetOptionValue(it->name); |
|
skamonkey@3574
|
310 |
bool allowMulti = ( options && strstr(options, "allowmultiple") != NULL ); |
|
skamonkey@3574
|
311 |
bool allowMidfunc = ( options && strstr(options, "allowmidfunc") != NULL ); |
|
skamonkey@3574
|
312 |
|
|
skamonkey@3574
|
313 |
bool bWinGood = false; |
|
skamonkey@3574
|
314 |
if( !hasWindows ) { |
|
skamonkey@3574
|
315 |
snprintf( winStatus, sizeof(winStatus), "UNKNOWN" ); |
|
skamonkey@3574
|
316 |
} |
|
skamonkey@3574
|
317 |
else if( windowsMatches == -1 && !allowMidfunc) { |
|
skamonkey@3574
|
318 |
snprintf( winStatus, sizeof(winStatus), "MIDFUNC" ); |
|
skamonkey@3574
|
319 |
} |
|
skamonkey@3574
|
320 |
else if( windowsMatches == 0 ) { |
|
skamonkey@3574
|
321 |
snprintf( winStatus, sizeof(winStatus), "NOTFOUND" ); |
|
skamonkey@3574
|
322 |
} |
|
skamonkey@3574
|
323 |
else if( windowsMatches > 1 && !allowMulti) { |
|
skamonkey@3574
|
324 |
snprintf( winStatus, sizeof(winStatus), "MULTIPLE" ); |
|
skamonkey@3574
|
325 |
} |
|
skamonkey@3574
|
326 |
else { |
|
skamonkey@3574
|
327 |
bWinGood = true; |
|
skamonkey@3574
|
328 |
snprintf( winStatus, sizeof(winStatus), "GOOD" ); |
|
skamonkey@3574
|
329 |
} |
|
skamonkey@3574
|
330 |
|
|
skamonkey@3574
|
331 |
char linStatus[16]; |
|
skamonkey@3574
|
332 |
bool bLinGood = false; |
|
skamonkey@3574
|
333 |
if( !hasLinux ) { |
|
skamonkey@3574
|
334 |
snprintf( linStatus, sizeof(linStatus), "UNKNOWN" ); |
|
skamonkey@3574
|
335 |
} |
|
skamonkey@3574
|
336 |
else if( linuxMatches == 0 ) { |
|
skamonkey@3574
|
337 |
snprintf( linStatus, sizeof(linStatus), "NOTFOUND" ); |
|
skamonkey@3574
|
338 |
} |
|
skamonkey@3574
|
339 |
else if( linuxMatches == 1 ) { |
|
skamonkey@3574
|
340 |
bLinGood = true; |
|
skamonkey@3574
|
341 |
snprintf( linStatus, sizeof(linStatus), "GOOD" ); |
|
skamonkey@3574
|
342 |
} |
|
skamonkey@3574
|
343 |
else { |
|
skamonkey@3574
|
344 |
snprintf( linStatus, sizeof(linStatus), "CHECK" ); |
|
skamonkey@3574
|
345 |
} |
|
skamonkey@3574
|
346 |
|
|
skamonkey@3574
|
347 |
bool showWinExtra = (hasWindows && !bWinGood); |
|
skamonkey@3574
|
348 |
bool showLinExtra = ( ( hasLinux && !bLinGood ) || showWinExtra ); |
|
skamonkey@3574
|
349 |
|
|
skamonkey@3574
|
350 |
printf("%s S: %-22s (%s)", (showWinExtra || showLinExtra) ? "!" : " ", it->name, (it->lib == Server) ? "server" : "engine" ); |
|
skamonkey@3574
|
351 |
printf(" - w: %-8s - l: %-8s\n", winStatus, linStatus ); |
|
skamonkey@3574
|
352 |
|
|
skamonkey@3574
|
353 |
if( showWinExtra || showLinExtra ) |
|
skamonkey@3574
|
354 |
printf( "! current:\n" ); |
|
skamonkey@3574
|
355 |
|
|
skamonkey@3574
|
356 |
if( showWinExtra ) |
|
skamonkey@3574
|
357 |
{ |
|
skamonkey@3574
|
358 |
printf("! w: \"%s\"\n", |
|
skamonkey@3574
|
359 |
winSymbol ? winSymbol : "" |
|
skamonkey@3513
|
360 |
); |
|
skamonkey@3574
|
361 |
} |
|
skamonkey@3513
|
362 |
|
|
skamonkey@3574
|
363 |
if( showLinExtra ) |
|
skamonkey@3574
|
364 |
{ |
|
skamonkey@3574
|
365 |
// extra \n at end is intentional to add buffer after possibly long sigs |
|
skamonkey@3574
|
366 |
printf("! l: \"%s\"\n\n", |
|
skamonkey@3574
|
367 |
linSymbol ? linSymbol : "" |
|
skamonkey@3574
|
368 |
); |
|
skamonkey@3574
|
369 |
} |
|
skamonkey@3513
|
370 |
} |
|
skamonkey@3513
|
371 |
} |
|
skamonkey@3513
|
372 |
|
|
skamonkey@3513
|
373 |
return 0; |
|
skamonkey@3513
|
374 |
} |
|
Dr!fter@3954
|
375 |
void CheckWindowsSigOffset(char* name, const char* symbol, int file) |
|
Dr!fter@3954
|
376 |
{ |
|
Dr!fter@3954
|
377 |
void *ptr = GetWindowsSigPtr(file, symbol); |
|
Dr!fter@3954
|
378 |
if(!ptr) |
|
Dr!fter@3954
|
379 |
{ |
|
Dr!fter@3954
|
380 |
return; |
|
Dr!fter@3954
|
381 |
} |
|
Dr!fter@3954
|
382 |
const char* sigOffsetKey = NULL; |
|
Dr!fter@3954
|
383 |
const char* sigOffsetByte = NULL; |
|
Dr!fter@3954
|
384 |
int sigOffset = -1; |
|
Dr!fter@3954
|
385 |
char sigOffsetName[128]; |
|
Dr!fter@3954
|
386 |
char sigByteName[128]; |
|
skamonkey@3513
|
387 |
|
|
Dr!fter@3954
|
388 |
snprintf(sigOffsetName, sizeof(sigOffsetName), "%s_Offset", name); |
|
Dr!fter@3954
|
389 |
snprintf(sigByteName, sizeof(sigByteName), "%s_Byte_Win", name); |
|
Dr!fter@3954
|
390 |
|
|
Dr!fter@3954
|
391 |
sigOffsetKey = symbols.GetKeyValue((const char *)sigOffsetName); |
|
Dr!fter@3954
|
392 |
if(sigOffsetKey == NULL) |
|
Dr!fter@3954
|
393 |
{ |
|
Dr!fter@3954
|
394 |
|
|
Dr!fter@3954
|
395 |
//Maybe it has multiple? |
|
Dr!fter@3954
|
396 |
for(unsigned int i = 1; i <= 4; i++) |
|
Dr!fter@3954
|
397 |
{ |
|
Dr!fter@3954
|
398 |
snprintf(sigOffsetName, sizeof(sigOffsetName), "%s_Offset%i", name, i); |
|
Dr!fter@3954
|
399 |
snprintf(sigByteName, sizeof(sigByteName), "%s_Byte_Win%i", name, i); |
|
Dr!fter@3954
|
400 |
sigOffsetKey = symbols.GetKeyValue((const char *)sigOffsetName); |
|
Dr!fter@3954
|
401 |
|
|
Dr!fter@3954
|
402 |
if(sigOffsetKey == NULL) |
|
Dr!fter@3954
|
403 |
{ |
|
Dr!fter@3954
|
404 |
break; |
|
Dr!fter@3954
|
405 |
} |
|
Dr!fter@3954
|
406 |
|
|
Dr!fter@3954
|
407 |
sigOffset = GetOffset(sigOffsetKey, true); |
|
Dr!fter@3954
|
408 |
sigOffsetByte = symbols.GetKeyValue((const char *)sigByteName); |
|
Dr!fter@3954
|
409 |
|
|
Dr!fter@3954
|
410 |
if(sigOffset != -1 && sigOffsetByte != NULL)//Got the offset in the function |
|
Dr!fter@3954
|
411 |
{ |
|
Dr!fter@3954
|
412 |
uint8_t iByte = strtoul(sigOffsetByte, NULL, 16); |
|
Dr!fter@3954
|
413 |
|
|
Dr!fter@3954
|
414 |
if(iByte == *(uint8_t *)((intptr_t)ptr + sigOffset)) |
|
Dr!fter@3954
|
415 |
{ |
|
Dr!fter@3954
|
416 |
printf(" w: %s -> %s (%4d) == \\x%s GOOD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); |
|
Dr!fter@3954
|
417 |
} |
|
Dr!fter@3954
|
418 |
else |
|
Dr!fter@3954
|
419 |
{ |
|
Dr!fter@3954
|
420 |
printf("! w: %s -> %s (%4d) != \\x%s BAD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); |
|
Dr!fter@3954
|
421 |
} |
|
Dr!fter@3954
|
422 |
} |
|
Dr!fter@3954
|
423 |
} |
|
Dr!fter@3954
|
424 |
} |
|
Dr!fter@3954
|
425 |
else |
|
Dr!fter@3954
|
426 |
{ |
|
Dr!fter@3954
|
427 |
sigOffset = GetOffset(sigOffsetKey, true); |
|
Dr!fter@3954
|
428 |
sigOffsetByte = symbols.GetKeyValue((const char *)sigByteName); |
|
Dr!fter@3954
|
429 |
|
|
Dr!fter@3954
|
430 |
if(sigOffset != -1 && sigOffsetByte != NULL)//Got the offset in the function |
|
Dr!fter@3954
|
431 |
{ |
|
Dr!fter@3954
|
432 |
uint8_t iByte = strtoul(sigOffsetByte, NULL, 16); |
|
Dr!fter@3954
|
433 |
|
|
Dr!fter@3954
|
434 |
if(iByte == *(uint8_t *)((intptr_t)ptr + sigOffset)) |
|
Dr!fter@3954
|
435 |
{ |
|
Dr!fter@3954
|
436 |
printf(" w: %s -> %s (%4d) == \\x%s GOOD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); |
|
Dr!fter@3954
|
437 |
} |
|
Dr!fter@3954
|
438 |
else |
|
Dr!fter@3954
|
439 |
{ |
|
Dr!fter@3954
|
440 |
printf("! w: %s -> %s (%4d) != \\x%s BAD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); |
|
Dr!fter@3954
|
441 |
} |
|
Dr!fter@3954
|
442 |
} |
|
Dr!fter@3954
|
443 |
} |
|
Dr!fter@3954
|
444 |
} |
|
Dr!fter@3954
|
445 |
void CheckLinuxSigOffset(char* name, const char* symbol, void * handle) |
|
Dr!fter@3954
|
446 |
{ |
|
Dr!fter@3954
|
447 |
void *ptr = GetLinuxSigPtr(handle, symbol); |
|
Dr!fter@3954
|
448 |
if(!ptr) |
|
Dr!fter@3954
|
449 |
{ |
|
Dr!fter@3954
|
450 |
return; |
|
Dr!fter@3954
|
451 |
} |
|
Dr!fter@3954
|
452 |
const char* sigOffsetKey = NULL; |
|
Dr!fter@3954
|
453 |
const char* sigOffsetByte = NULL; |
|
Dr!fter@3954
|
454 |
int sigOffset = -1; |
|
Dr!fter@3954
|
455 |
char sigOffsetName[128]; |
|
Dr!fter@3954
|
456 |
char sigByteName[128]; |
|
Dr!fter@3954
|
457 |
|
|
Dr!fter@3954
|
458 |
snprintf(sigOffsetName, sizeof(sigOffsetName), "%s_Offset", name); |
|
Dr!fter@3954
|
459 |
snprintf(sigByteName, sizeof(sigByteName), "%s_Byte_Lin", name); |
|
Dr!fter@3954
|
460 |
|
|
Dr!fter@3954
|
461 |
sigOffsetKey = symbols.GetKeyValue((const char *)sigOffsetName); |
|
Dr!fter@3954
|
462 |
|
|
Dr!fter@3954
|
463 |
if(sigOffsetKey == NULL) |
|
Dr!fter@3954
|
464 |
{ |
|
Dr!fter@3954
|
465 |
|
|
Dr!fter@3954
|
466 |
//Maybe it has multiple? |
|
Dr!fter@3954
|
467 |
for(unsigned int i = 1; i <= 4; i++) |
|
Dr!fter@3954
|
468 |
{ |
|
Dr!fter@3954
|
469 |
snprintf(sigOffsetName, sizeof(sigOffsetName), "%s_Offset%i", name, i); |
|
Dr!fter@3954
|
470 |
snprintf(sigByteName, sizeof(sigByteName), "%s_Byte_Lin%i", name, i); |
|
Dr!fter@3954
|
471 |
sigOffsetKey = symbols.GetKeyValue((const char *)sigOffsetName); |
|
Dr!fter@3954
|
472 |
|
|
Dr!fter@3954
|
473 |
if(sigOffsetKey == NULL) |
|
Dr!fter@3954
|
474 |
{ |
|
Dr!fter@3954
|
475 |
break; |
|
Dr!fter@3954
|
476 |
} |
|
Dr!fter@3954
|
477 |
|
|
Dr!fter@3954
|
478 |
sigOffset = GetOffset(sigOffsetKey, false); |
|
Dr!fter@3954
|
479 |
sigOffsetByte = symbols.GetKeyValue((const char *)sigByteName); |
|
Dr!fter@3954
|
480 |
|
|
Dr!fter@3954
|
481 |
if(sigOffset != -1 && sigOffsetByte != NULL)//Got the offset in the function |
|
Dr!fter@3954
|
482 |
{ |
|
Dr!fter@3954
|
483 |
uint8_t iByte = strtoul(sigOffsetByte, NULL, 16); |
|
Dr!fter@3954
|
484 |
|
|
Dr!fter@3954
|
485 |
if(iByte == *(uint8_t *)((intptr_t)ptr + sigOffset)) |
|
Dr!fter@3954
|
486 |
{ |
|
Dr!fter@3954
|
487 |
printf(" l: %s -> %s (%4d) == \\x%s GOOD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); |
|
Dr!fter@3954
|
488 |
} |
|
Dr!fter@3954
|
489 |
else |
|
Dr!fter@3954
|
490 |
{ |
|
Dr!fter@3954
|
491 |
printf("! l: %s -> %s (%4d) != \\x%s BAD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); |
|
Dr!fter@3954
|
492 |
} |
|
Dr!fter@3954
|
493 |
} |
|
Dr!fter@3954
|
494 |
} |
|
Dr!fter@3954
|
495 |
} |
|
Dr!fter@3954
|
496 |
else |
|
Dr!fter@3954
|
497 |
{ |
|
Dr!fter@3956
|
498 |
sigOffset = GetOffset(sigOffsetKey, false); |
|
Dr!fter@3954
|
499 |
sigOffsetByte = symbols.GetKeyValue((const char *)sigByteName); |
|
Dr!fter@3954
|
500 |
|
|
Dr!fter@3954
|
501 |
if(sigOffset != -1 && sigOffsetByte != NULL)//Got the offset in the function |
|
Dr!fter@3954
|
502 |
{ |
|
Dr!fter@3954
|
503 |
uint8_t iByte = strtoul(sigOffsetByte, NULL, 16); |
|
Dr!fter@3954
|
504 |
|
|
Dr!fter@3954
|
505 |
if(iByte == *(uint8_t *)((intptr_t)ptr + sigOffset)) |
|
Dr!fter@3954
|
506 |
{ |
|
Dr!fter@3954
|
507 |
printf(" l: %s -> %s (%4d) == \\x%s GOOD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); |
|
Dr!fter@3954
|
508 |
} |
|
Dr!fter@3954
|
509 |
else |
|
Dr!fter@3954
|
510 |
{ |
|
Dr!fter@3954
|
511 |
printf("! l: %s -> %s (%4d) != \\x%s BAD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); |
|
Dr!fter@3954
|
512 |
} |
|
Dr!fter@3954
|
513 |
} |
|
Dr!fter@3954
|
514 |
} |
|
Dr!fter@3954
|
515 |
} |
|
Dr!fter@3954
|
516 |
int GetOffset(const char* key, bool windows) |
|
Dr!fter@3954
|
517 |
{ |
|
Dr!fter@3954
|
518 |
for (list<Offset>::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++) |
|
Dr!fter@3954
|
519 |
{ |
|
Dr!fter@3954
|
520 |
if (strcmp(it->name, key) == 0) |
|
Dr!fter@3954
|
521 |
{ |
|
Dr!fter@3954
|
522 |
if(windows) |
|
Dr!fter@3954
|
523 |
return it->win; |
|
Dr!fter@3954
|
524 |
else |
|
Dr!fter@3954
|
525 |
return it->lin; |
|
Dr!fter@3954
|
526 |
} |
|
Dr!fter@3954
|
527 |
} |
|
Dr!fter@3954
|
528 |
return -1; |
|
Dr!fter@3954
|
529 |
} |
|
Dr!fter@3954
|
530 |
void *GetWindowsSigPtr(int file, const char* symbol) |
|
Dr!fter@3954
|
531 |
{ |
|
Dr!fter@3954
|
532 |
int matches = 0; |
|
Dr!fter@3954
|
533 |
bool atFuncStart = true; |
|
Dr!fter@3954
|
534 |
bool isAt = (symbol[0] == '@'); |
|
Dr!fter@3954
|
535 |
// we can't support this on windows from here |
|
Dr!fter@3954
|
536 |
if (isAt) |
|
Dr!fter@3954
|
537 |
return NULL; |
|
Dr!fter@3954
|
538 |
|
|
Dr!fter@3954
|
539 |
unsigned char real_sig[511]; |
|
Dr!fter@3954
|
540 |
size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol); |
|
Dr!fter@3954
|
541 |
|
|
Dr!fter@3954
|
542 |
if (real_bytes >= 1) |
|
Dr!fter@3954
|
543 |
{ |
|
Dr!fter@3954
|
544 |
return mu.FindPatternInFile(file, (char*)real_sig, real_bytes, matches, atFuncStart); |
|
Dr!fter@3954
|
545 |
} |
|
Dr!fter@3954
|
546 |
return NULL; |
|
Dr!fter@3954
|
547 |
|
|
Dr!fter@3954
|
548 |
} |
|
Dr!fter@3954
|
549 |
void *GetLinuxSigPtr(void *handle, const char* symbol) |
|
Dr!fter@3954
|
550 |
{ |
|
Dr!fter@3954
|
551 |
bool isAt = (symbol[0] == '@' && symbol[1] != '\0'); |
|
Dr!fter@3954
|
552 |
int matches = 0; |
|
Dr!fter@3954
|
553 |
bool dummy; |
|
Dr!fter@3954
|
554 |
|
|
Dr!fter@3954
|
555 |
if (isAt) |
|
Dr!fter@3954
|
556 |
{ |
|
Dr!fter@3954
|
557 |
if( use_symtab && mu.ResolveSymbol(handle, &symbol[1]) ) |
|
Dr!fter@3954
|
558 |
return mu.ResolveSymbol(handle, &symbol[1]); |
|
Dr!fter@3954
|
559 |
else if( !use_symtab && dlsym(handle, &symbol[1]) ) |
|
Dr!fter@3954
|
560 |
return dlsym(handle, &symbol[1]); |
|
Dr!fter@3954
|
561 |
} |
|
Dr!fter@3954
|
562 |
else |
|
Dr!fter@3954
|
563 |
{ |
|
Dr!fter@3954
|
564 |
unsigned char real_sig[511]; |
|
Dr!fter@3954
|
565 |
size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol); |
|
Dr!fter@3954
|
566 |
|
|
Dr!fter@3954
|
567 |
if (real_bytes >= 1) |
|
Dr!fter@3954
|
568 |
{ |
|
Dr!fter@3954
|
569 |
return mu.FindPattern(handle, (char*)real_sig, real_bytes, matches, dummy); |
|
Dr!fter@3954
|
570 |
} |
|
Dr!fter@3954
|
571 |
} |
|
Dr!fter@3954
|
572 |
|
|
Dr!fter@3954
|
573 |
return NULL; |
|
Dr!fter@3954
|
574 |
} |
|
skamonkey@3574
|
575 |
int checkSigStringW(int file, const char* symbol) |
|
skamonkey@3513
|
576 |
{ |
|
skamonkey@3574
|
577 |
int matches = 0; |
|
skamonkey@3574
|
578 |
bool atFuncStart = true; |
|
skamonkey@3513
|
579 |
bool isAt = (symbol[0] == '@'); |
|
skamonkey@3513
|
580 |
// we can't support this on windows from here |
|
skamonkey@3513
|
581 |
if (isAt) |
|
skamonkey@3513
|
582 |
return false; |
|
skamonkey@3513
|
583 |
|
|
skamonkey@3513
|
584 |
unsigned char real_sig[511]; |
|
skamonkey@3513
|
585 |
size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol); |
|
skamonkey@3513
|
586 |
|
|
skamonkey@3513
|
587 |
if (real_bytes >= 1) |
|
skamonkey@3513
|
588 |
{ |
|
skamonkey@3574
|
589 |
mu.FindPatternInFile(file, (char*)real_sig, real_bytes, matches, atFuncStart); |
|
skamonkey@3513
|
590 |
} |
|
skamonkey@3513
|
591 |
|
|
skamonkey@3574
|
592 |
if( !atFuncStart ) |
|
skamonkey@3574
|
593 |
return -1; |
|
skamonkey@3513
|
594 |
|
|
skamonkey@3574
|
595 |
return matches; |
|
skamonkey@3513
|
596 |
} |
|
skamonkey@3513
|
597 |
|
|
skamonkey@3574
|
598 |
int checkSigStringL(void *handle, const char* symbol) |
|
skamonkey@3513
|
599 |
{ |
|
skamonkey@3742
|
600 |
bool isAt = (symbol[0] == '@' && symbol[1] != '\0'); |
|
skamonkey@3574
|
601 |
int matches = 0; |
|
skamonkey@3574
|
602 |
bool dummy; |
|
skamonkey@3513
|
603 |
|
|
skamonkey@3513
|
604 |
if (isAt) |
|
skamonkey@3513
|
605 |
{ |
|
skamonkey@3742
|
606 |
if( use_symtab && mu.ResolveSymbol(handle, &symbol[1]) ) |
|
skamonkey@3742
|
607 |
matches = 1; |
|
skamonkey@3742
|
608 |
else if( !use_symtab && dlsym(handle, &symbol[1]) ) |
|
skamonkey@3574
|
609 |
matches = 1; |
|
skamonkey@3513
|
610 |
} |
|
skamonkey@3513
|
611 |
else |
|
skamonkey@3513
|
612 |
{ |
|
skamonkey@3513
|
613 |
unsigned char real_sig[511]; |
|
skamonkey@3513
|
614 |
size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol); |
|
skamonkey@3513
|
615 |
|
|
skamonkey@3513
|
616 |
if (real_bytes >= 1) |
|
skamonkey@3513
|
617 |
{ |
|
skamonkey@3574
|
618 |
mu.FindPattern(handle, (char*)real_sig, real_bytes, matches, dummy); |
|
skamonkey@3513
|
619 |
} |
|
skamonkey@3513
|
620 |
} |
|
skamonkey@3513
|
621 |
|
|
skamonkey@3574
|
622 |
return matches; |
|
skamonkey@3513
|
623 |
} |
|
skamonkey@3513
|
624 |
|
|
skamonkey@3513
|
625 |
/* |
|
skamonkey@3513
|
626 |
takes a mangled member function symbol and returns the position where the function name and parameters start |
|
skamonkey@3513
|
627 |
01234567890123456789012345678 |
|
skamonkey@3513
|
628 |
_ZN9CTFPlayer12ForceRespawnEv |
|
skamonkey@3513
|
629 |
^13 ^28 |
|
skamonkey@3513
|
630 |
*/ |
|
skamonkey@3513
|
631 |
void findFuncPos(const char *sym, int &func, int ¶ms) |
|
skamonkey@3513
|
632 |
{ |
|
skamonkey@3513
|
633 |
int i = 0; |
|
skamonkey@3513
|
634 |
while ((sym[i] < '0') || (sym[i] > '9')) i++; |
|
skamonkey@3513
|
635 |
int classLen = atoi(sym + i); |
|
skamonkey@3513
|
636 |
func = i + (int)ceil(log10(classLen)) + classLen; |
|
skamonkey@3513
|
637 |
int funcLen = atoi(sym + func); |
|
skamonkey@3513
|
638 |
params = func + (int)ceil(log10(funcLen)) + funcLen; |
|
skamonkey@3513
|
639 |
} |
|
skamonkey@3513
|
640 |
|
|
skamonkey@3513
|
641 |
int findVFunc(void *handle, void **vt, const char *symbol) |
|
skamonkey@3513
|
642 |
{ |
|
skamonkey@3742
|
643 |
if( !use_symtab ) |
|
skamonkey@3742
|
644 |
{ |
|
skamonkey@3742
|
645 |
for (int i = 0; i < 1000; i++ ) |
|
skamonkey@3742
|
646 |
{ |
|
skamonkey@3742
|
647 |
void *pFunc = vt[i]; |
|
skamonkey@3742
|
648 |
if( !pFunc ) |
|
skamonkey@3742
|
649 |
continue; |
|
skamonkey@3742
|
650 |
|
|
skamonkey@3742
|
651 |
if( pFunc == dlsym(handle, symbol ) ) |
|
skamonkey@3742
|
652 |
return i - 2; |
|
skamonkey@3742
|
653 |
} |
|
skamonkey@3742
|
654 |
|
|
skamonkey@3742
|
655 |
return -1; |
|
skamonkey@3742
|
656 |
} |
|
skamonkey@3742
|
657 |
|
|
skamonkey@3513
|
658 |
int funcPos, paramPos; |
|
skamonkey@3513
|
659 |
findFuncPos(symbol, funcPos, paramPos); |
|
skamonkey@3513
|
660 |
|
|
skamonkey@3513
|
661 |
for (int i = 0; i < 1000; i++) |
|
skamonkey@3513
|
662 |
{ |
|
skamonkey@3513
|
663 |
void *pFunc = vt[i]; |
|
skamonkey@3742
|
664 |
if( !pFunc ) |
|
skamonkey@3742
|
665 |
continue; |
|
skamonkey@3742
|
666 |
|
|
skamonkey@3513
|
667 |
const char *s; |
|
skamonkey@3513
|
668 |
|
|
skamonkey@3513
|
669 |
if (!(s = mu.ResolveAddr(handle, pFunc))) |
|
skamonkey@3513
|
670 |
continue; |
|
skamonkey@3513
|
671 |
|
|
skamonkey@3513
|
672 |
if ((i > 1) && (strncmp(s, "_ZTI", 4) == 0)) |
|
skamonkey@3513
|
673 |
break; |
|
skamonkey@3513
|
674 |
|
|
skamonkey@3513
|
675 |
|
|
skamonkey@3513
|
676 |
int tempFuncPos, tempParamPos; |
|
skamonkey@3513
|
677 |
findFuncPos(s, tempFuncPos, tempParamPos); |
|
skamonkey@3513
|
678 |
|
|
skamonkey@3513
|
679 |
if (strcmp(s + tempFuncPos, symbol + funcPos) == 0) |
|
skamonkey@3513
|
680 |
{ |
|
skamonkey@3742
|
681 |
return i - 2; |
|
skamonkey@3513
|
682 |
} |
|
skamonkey@3513
|
683 |
} |
|
skamonkey@3513
|
684 |
|
|
skamonkey@3742
|
685 |
return -1; |
|
skamonkey@3513
|
686 |
} |
|
skamonkey@3513
|
687 |
|
|
skamonkey@3513
|
688 |
unsigned int strncopy(char *dest, const char *src, size_t count) |
|
skamonkey@3513
|
689 |
{ |
|
skamonkey@3513
|
690 |
if (!count) |
|
skamonkey@3513
|
691 |
{ |
|
skamonkey@3513
|
692 |
return 0; |
|
skamonkey@3513
|
693 |
} |
|
skamonkey@3513
|
694 |
|
|
skamonkey@3513
|
695 |
char *start = dest; |
|
skamonkey@3513
|
696 |
while ((*src) && (--count)) |
|
skamonkey@3513
|
697 |
{ |
|
skamonkey@3513
|
698 |
*dest++ = *src++; |
|
skamonkey@3513
|
699 |
} |
|
skamonkey@3513
|
700 |
*dest = '\0'; |
|
skamonkey@3513
|
701 |
|
|
skamonkey@3513
|
702 |
return (dest - start); |
|
skamonkey@3513
|
703 |
} |
|
skamonkey@3513
|
704 |
|
|
skamonkey@3513
|
705 |
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) |
|
skamonkey@3513
|
706 |
{ |
|
skamonkey@3513
|
707 |
va_list ap; |
|
skamonkey@3513
|
708 |
va_start(ap, fmt); |
|
skamonkey@3513
|
709 |
size_t len = vsnprintf(buffer, maxlength, fmt, ap); |
|
skamonkey@3513
|
710 |
va_end(ap); |
|
skamonkey@3513
|
711 |
|
|
skamonkey@3513
|
712 |
if (len >= maxlength) |
|
skamonkey@3513
|
713 |
{ |
|
skamonkey@3513
|
714 |
buffer[maxlength - 1] = '\0'; |
|
skamonkey@3513
|
715 |
return (maxlength - 1); |
|
skamonkey@3513
|
716 |
} |
|
skamonkey@3513
|
717 |
else |
|
skamonkey@3513
|
718 |
{ |
|
skamonkey@3513
|
719 |
return len; |
|
skamonkey@3513
|
720 |
} |
|
skamonkey@3513
|
721 |
} |
|
skamonkey@3513
|
722 |
|
|
skamonkey@3513
|
723 |
size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr) |
|
skamonkey@3513
|
724 |
{ |
|
skamonkey@3513
|
725 |
size_t written = 0; |
|
skamonkey@3513
|
726 |
size_t length = strlen(hexstr); |
|
skamonkey@3513
|
727 |
|
|
skamonkey@3513
|
728 |
for (size_t i = 0; i < length; i++) |
|
skamonkey@3513
|
729 |
{ |
|
skamonkey@3513
|
730 |
if (written >= maxlength) |
|
skamonkey@3513
|
731 |
break; |
|
skamonkey@3513
|
732 |
|
|
skamonkey@3513
|
733 |
buffer[written++] = hexstr[i]; |
|
skamonkey@3513
|
734 |
if (hexstr[i] == '\\' && hexstr[i + 1] == 'x') |
|
skamonkey@3513
|
735 |
{ |
|
skamonkey@3513
|
736 |
if (i + 3 >= length) |
|
skamonkey@3513
|
737 |
continue; |
|
skamonkey@3513
|
738 |
/* Get the hex part. */ |
|
skamonkey@3513
|
739 |
char s_byte[3]; |
|
skamonkey@3513
|
740 |
int r_byte; |
|
skamonkey@3513
|
741 |
s_byte[0] = hexstr[i + 2]; |
|
skamonkey@3513
|
742 |
s_byte[1] = hexstr[i + 3]; |
|
skamonkey@3513
|
743 |
s_byte[2] = '\0'; |
|
skamonkey@3513
|
744 |
/* Read it as an integer */ |
|
skamonkey@3513
|
745 |
sscanf(s_byte, "%x", &r_byte); |
|
skamonkey@3513
|
746 |
/* Save the value */ |
|
skamonkey@3513
|
747 |
buffer[written - 1] = r_byte; |
|
skamonkey@3513
|
748 |
/* Adjust index */ |
|
skamonkey@3513
|
749 |
i += 3; |
|
skamonkey@3513
|
750 |
} |
|
skamonkey@3513
|
751 |
} |
|
skamonkey@3513
|
752 |
|
|
skamonkey@3513
|
753 |
return written; |
|
skamonkey@3513
|
754 |
} |
|
skamonkey@3513
|
755 |
|