tools/gdc-psyfork/gdc.cpp
changeset 3574 b51285ca203f
parent 3513 50b5b98b3400
child 3742 80034eb49c32
     1.1 --- a/tools/gdc-psyfork/gdc.cpp	Tue Jul 03 07:51:12 2012 -0400
     1.2 +++ b/tools/gdc-psyfork/gdc.cpp	Tue Jul 03 10:27:27 2012 -0400
     1.3 @@ -3,6 +3,7 @@
     1.4  #include <dlfcn.h>
     1.5  #include <fcntl.h>
     1.6  #include <math.h>
     1.7 +#include <iostream>
     1.8  #include "gdc.h"
     1.9  #include "GameConfigs.h"
    1.10  #include "MemoryUtils.h"
    1.11 @@ -16,6 +17,11 @@
    1.12  char *wgame_binary = NULL;
    1.13  char *wengine_binary = NULL;
    1.14  
    1.15 +inline bool IsDigit( char c )
    1.16 +{
    1.17 +	return c < 58 && c > 47;
    1.18 +}
    1.19 +
    1.20  int main(int argc, char **argv)
    1.21  {
    1.22  	char *gamedata = NULL;
    1.23 @@ -125,26 +131,6 @@
    1.24  		return 0;
    1.25  	}
    1.26  
    1.27 -	const char *vtsym = symbols.GetKeyValue("vtsym");
    1.28 -	if (!vtsym)
    1.29 -	{
    1.30 -		printf("Couldn't find vtsym\n");
    1.31 -		return 0;
    1.32 -	}
    1.33 -
    1.34 -	void **vt = (void**) mu.ResolveSymbol(ghandle, vtsym);
    1.35 -	if (!vt)
    1.36 -	{
    1.37 -		printf("Couldn't find vtable %s\n", vtsym);
    1.38 -		dlclose(ghandle);
    1.39 -		dlclose(ehandle);
    1.40 -		close(wgfile);
    1.41 -		close(wefile);
    1.42 -
    1.43 -		return 0;
    1.44 -	}
    1.45 -
    1.46 -
    1.47  	for (list<Offset>::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++)
    1.48  	{
    1.49  		if (debug)
    1.50 @@ -155,34 +141,60 @@
    1.51  		const char *symbol = symbols.GetKeyValue(it->name);
    1.52  		if (symbol)
    1.53  		{
    1.54 +			char symvt[128] = "_ZTV";
    1.55 +			bool bGotFirstNumbers = false;
    1.56 +			bool bLastNumberDigit = false;
    1.57 +			unsigned int symlen = strlen(symbol);
    1.58 +			unsigned int pos = strlen(symvt);
    1.59 +			
    1.60 +			for ( unsigned int i = 0; i < symlen && pos < (sizeof(symvt)-1); ++i )
    1.61 +			{
    1.62 +				bool isDigit = IsDigit( symbol[i] );
    1.63 +				if( !isDigit && bLastNumberDigit )
    1.64 +				{
    1.65 +					bGotFirstNumbers = true;
    1.66 +				}
    1.67 +				
    1.68 +				// we're before the class len
    1.69 +				if( !bGotFirstNumbers && !isDigit )
    1.70 +					continue;
    1.71 +				
    1.72 +				// we're at the function name len
    1.73 +				if( bGotFirstNumbers && isDigit )
    1.74 +				{
    1.75 +					symvt[pos] = 0;
    1.76 +					break;
    1.77 +				}
    1.78 +				
    1.79 +				// we're at the class len or class name. we want these
    1.80 +				symvt[pos++] = symbol[i];
    1.81 +				if( isDigit )
    1.82 +				{
    1.83 +					bLastNumberDigit = isDigit;
    1.84 +				}
    1.85 +			}
    1.86 +			symvt[pos] = 0;
    1.87 +			
    1.88  			int newOffset;
    1.89 -			char symvt[128];
    1.90 -			strcpy(symvt, it->name);
    1.91 -			strcat(symvt, "_vt");
    1.92 -			const char *newvtsym = symbols.GetKeyValue(symvt);
    1.93 -			if (newvtsym && newvtsym[0])
    1.94 +			if (symvt[0])
    1.95  			{
    1.96 -				void **newvt = (void**) mu.ResolveSymbol(ghandle, newvtsym);
    1.97 +				void **newvt = (void**) mu.ResolveSymbol(ghandle, symvt);
    1.98  			        if (!newvt)
    1.99  				{
   1.100 -					printf("O: %-22s - can't find, skipping\n", symvt);
   1.101 +					printf("? O: %-22s - can't find, skipping\n", symvt);
   1.102  					continue;
   1.103  				}
   1.104  
   1.105  				newOffset = findVFunc(ghandle, newvt, symbol);
   1.106  			}
   1.107 -			else
   1.108 -			{
   1.109 -				newOffset = findVFunc(ghandle, vt, symbol);
   1.110 -			}
   1.111  
   1.112  			if (newOffset == it->lin)
   1.113  			{
   1.114 -				printf("O: %-22s - GOOD.    current [ w: %3d, l: %3d ].\n", it->name, it->win, it->lin);
   1.115 +				printf("  O: %-22s - GOOD.    current [ w: %3d, l: %3d ].\n", it->name, it->win, it->lin);
   1.116  			}
   1.117  			else
   1.118  			{
   1.119 -				printf("O: %-22s - CHANGED. old [ w: %3d, l: %3d ]. new [ w: %3d, l: %3d ].\n",
   1.120 +				printf("! O: %-22s - CHANGED. old [ w: %3d, l: %3d ]. new [ w: %3d, l: %3d ].\n",
   1.121  					it->name,
   1.122  					it->win, it->lin,
   1.123  					newOffset - (it->lin - it->win), newOffset
   1.124 @@ -191,7 +203,7 @@
   1.125  		}
   1.126  		else // !symbol
   1.127  		{
   1.128 -			printf("O: %-22s - no Linux symbol, skipping\n", it->name);
   1.129 +			printf("  O: %-22s - no Linux symbol, skipping\n", it->name);
   1.130  		}
   1.131  	}
   1.132  
   1.133 @@ -210,7 +222,7 @@
   1.134  		bool hasWindows = (winSymbol && winSymbol[0]);
   1.135  		if (!hasLinux && !hasWindows)
   1.136  		{
   1.137 -			printf("S: %-22s - hasn't linux nor windows data, skipping\n", it->name);
   1.138 +			printf("  S: %-22s - hasn't linux nor windows data, skipping\n", it->name);
   1.139  			continue;
   1.140  		}
   1.141  		
   1.142 @@ -228,16 +240,17 @@
   1.143  		}
   1.144  		else
   1.145  		{
   1.146 -			printf("S: %-22s - isn't from server nor engine, skipping\n", it->name);
   1.147 +			printf("  S: %-22s - isn't from server nor engine, skipping\n", it->name);
   1.148  			continue;
   1.149  		}
   1.150  		
   1.151 -		bool foundLinux   = (!hasLinux   || checkSigStringL(linHandle, linSymbol));
   1.152 -		bool foundWindows = (!hasWindows || checkSigStringW(winFile,   winSymbol));
   1.153 +		int linuxMatches = 0, windowsMatches = 0;
   1.154 +		if( hasLinux )
   1.155 +			linuxMatches = checkSigStringL(linHandle, linSymbol);
   1.156 +		if( hasWindows )
   1.157 +			windowsMatches = checkSigStringW(winFile,   winSymbol);
   1.158  			
   1.159 -		// Prepare for ternery ABUSE
   1.160 -		
   1.161 -		if (foundLinux && foundWindows)
   1.162 +		if (linuxMatches == 1 && windowsMatches == 1)
   1.163  		{
   1.164  			// too much clutter to print current data if it matches anyway, unlike with offsets
   1.165  			/*
   1.166 @@ -248,42 +261,86 @@
   1.167  				linSymbol ? linSymbol : ""
   1.168  				);
   1.169  			*/
   1.170 -			printf("S: %-22s (%s) - GOOD.\n",
   1.171 +			printf("  S: %-22s (%s) - w: GOOD     - l: GOOD    \n",
   1.172  				it->name,
   1.173  				(it->lib == Server) ? "server" : "engine"
   1.174  				);
   1.175  		}
   1.176  		else
   1.177  		{
   1.178 -			// extra \n at end is intentional to add buffer after possibly long sigs
   1.179 -			printf("S: %-22s (%s) - w: %s - l: %s\n%s%s%s%s%s%s%s%s\n",
   1.180 -					it->name,
   1.181 -					(it->lib == Server) ? "server" : "engine",
   1.182 -					hasWindows ? (foundWindows ? "GOOD" : "CHANGED") : "UNKNOWN",
   1.183 -					hasLinux   ? (foundLinux   ? "GOOD" : "CHANGED") : "UNKNOWN",
   1.184 -					
   1.185 -					hasWindows ? "\tcurrent - w: " : "",
   1.186 -					(hasWindows && foundWindows) ? "    (found) \"" : (hasWindows ? "(NOT found) \"" : ""),
   1.187 -					(hasWindows && winSymbol)  ? winSymbol : "",
   1.188 -					hasWindows ? "\"\n" : "",
   1.189 -					
   1.190 -					hasLinux ? "\tcurrent - l: " : "",
   1.191 -					(hasLinux && foundLinux) ? "    (found) \"" : (hasLinux ? "(NOT found) \"" : ""),
   1.192 -					(hasLinux && linSymbol)  ? linSymbol : "",
   1.193 -					hasLinux ? "\"\n" : ""
   1.194 +			char winStatus[16];
   1.195 +			// right now the only option is to ignore
   1.196 +			const char *options = symbols.GetOptionValue(it->name);
   1.197 +			bool allowMulti = ( options && strstr(options, "allowmultiple") != NULL );
   1.198 +			bool allowMidfunc = ( options && strstr(options, "allowmidfunc") != NULL );
   1.199 +			
   1.200 +			bool bWinGood = false;
   1.201 +			if( !hasWindows ) {
   1.202 +				snprintf( winStatus, sizeof(winStatus), "UNKNOWN" );
   1.203 +			}
   1.204 +			else if( windowsMatches == -1 && !allowMidfunc) {
   1.205 +				snprintf( winStatus, sizeof(winStatus), "MIDFUNC" );
   1.206 +			}
   1.207 +			else if( windowsMatches == 0 ) {
   1.208 +				snprintf( winStatus, sizeof(winStatus), "NOTFOUND" );
   1.209 +			}
   1.210 +			else if( windowsMatches > 1 && !allowMulti) {
   1.211 +				snprintf( winStatus, sizeof(winStatus), "MULTIPLE" );
   1.212 +			}
   1.213 +			else {
   1.214 +				bWinGood = true;
   1.215 +				snprintf( winStatus, sizeof(winStatus), "GOOD" );
   1.216 +			}
   1.217 +			
   1.218 +			char linStatus[16];
   1.219 +			bool bLinGood = false;
   1.220 +			if( !hasLinux ) {
   1.221 +				snprintf( linStatus, sizeof(linStatus), "UNKNOWN" );
   1.222 +			}
   1.223 +			else if( linuxMatches == 0 ) {
   1.224 +				snprintf( linStatus, sizeof(linStatus), "NOTFOUND" );
   1.225 +			}
   1.226 +			else if( linuxMatches == 1 ) {
   1.227 +				bLinGood = true;
   1.228 +				snprintf( linStatus, sizeof(linStatus), "GOOD" );
   1.229 +			}
   1.230 +			else {
   1.231 +				snprintf( linStatus, sizeof(linStatus), "CHECK" );
   1.232 +			}
   1.233 +			
   1.234 +			bool showWinExtra = (hasWindows && !bWinGood);
   1.235 +			bool showLinExtra = ( ( hasLinux && !bLinGood ) || showWinExtra );
   1.236 +			
   1.237 +			printf("%s S: %-22s (%s)", (showWinExtra || showLinExtra) ? "!" : " ", it->name, (it->lib == Server) ? "server" : "engine" );
   1.238 +				printf(" - w: %-8s - l: %-8s\n", winStatus, linStatus );
   1.239 +			
   1.240 +			if( showWinExtra || showLinExtra )
   1.241 +				printf( "!    current:\n" );
   1.242 +			
   1.243 +			if( showWinExtra )
   1.244 +			{
   1.245 +				printf("!    w: \"%s\"\n",
   1.246 +					winSymbol ? winSymbol : ""
   1.247  					);
   1.248 +			}
   1.249  			
   1.250 +			if( showLinExtra )
   1.251 +			{
   1.252 +				// extra \n at end is intentional to add buffer after possibly long sigs
   1.253 +				printf("!    l: \"%s\"\n\n",
   1.254 +					linSymbol ? linSymbol : ""
   1.255 +					);
   1.256 +			}			
   1.257  		}
   1.258 -		
   1.259 -		//  j/k, no way that anyone could have been prepared for that
   1.260  	}
   1.261  
   1.262  	return 0;
   1.263  }
   1.264  
   1.265 -bool checkSigStringW(int file, const char* symbol)
   1.266 +int checkSigStringW(int file, const char* symbol)
   1.267  {
   1.268 -	void *addr = NULL;
   1.269 +	int matches = 0;
   1.270 +	bool atFuncStart = true;
   1.271  	bool isAt = (symbol[0] == '@');
   1.272  	// we can't support this on windows from here
   1.273  	if (isAt)
   1.274 @@ -294,23 +351,25 @@
   1.275  
   1.276  	if (real_bytes >= 1)
   1.277  	{
   1.278 -		addr = mu.FindPatternInFile(file, (char*)real_sig, real_bytes);
   1.279 +		mu.FindPatternInFile(file, (char*)real_sig, real_bytes, matches, atFuncStart);
   1.280  	}
   1.281  
   1.282 -	if (addr)
   1.283 -		return true;
   1.284 +	if( !atFuncStart )
   1.285 +		return -1;
   1.286  	
   1.287 -	return false;
   1.288 +	return matches;
   1.289  }
   1.290  
   1.291 -bool checkSigStringL(void *handle, const char* symbol)
   1.292 +int checkSigStringL(void *handle, const char* symbol)
   1.293  {
   1.294 -	void *addr = NULL;
   1.295  	bool isAt = (symbol[0] == '@');
   1.296 +	int matches = 0;
   1.297 +	bool dummy;
   1.298  	
   1.299  	if (isAt)
   1.300  	{
   1.301 -		addr = mu.ResolveSymbol(handle, symbol + 1);
   1.302 +		if( mu.ResolveSymbol(handle, symbol + 1) )
   1.303 +			matches = 1;
   1.304  	}
   1.305  	else
   1.306  	{
   1.307 @@ -319,14 +378,11 @@
   1.308  
   1.309  		if (real_bytes >= 1)
   1.310  		{
   1.311 -			addr = mu.FindPattern(handle, (char*)real_sig, real_bytes);
   1.312 +			mu.FindPattern(handle, (char*)real_sig, real_bytes, matches, dummy);
   1.313  		}
   1.314  	}
   1.315  
   1.316 -	if (addr)
   1.317 -		return true;
   1.318 -	
   1.319 -	return false;
   1.320 +	return matches;
   1.321  }
   1.322  
   1.323  /*