tools/gdc-psyfork/gdc.cpp
author Dr!fter
Thu Jul 18 20:34:11 2013 -0400 (2013-07-18)
changeset 3954 f98bbd1892df
parent 3742 80034eb49c32
child 3956 1ccbc1dfa814
permissions -rw-r--r--
Add signature offset byte check support for gdc-psyfork (NPOTB).
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@3954
   498
		sigOffset = GetOffset(sigOffsetKey, true);
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 &params)
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