tools/gdc/gdc.cpp
changeset 3129 76208f2e5ef0
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/gdc/gdc.cpp	Fri Oct 01 12:15:43 2010 -0700
     1.3 @@ -0,0 +1,266 @@
     1.4 +#include <stdio.h>
     1.5 +#include <unistd.h>
     1.6 +#include <dlfcn.h>
     1.7 +#include <math.h>
     1.8 +#include "gdc.h"
     1.9 +#include "GameConfigs.h"
    1.10 +#include "MemoryUtils.h"
    1.11 +
    1.12 +MemoryUtils mu;
    1.13 +
    1.14 +char *game = NULL;
    1.15 +char *engine = NULL;
    1.16 +char *binary = NULL;
    1.17 +
    1.18 +int main(int argc, char **argv)
    1.19 +{
    1.20 +	char *gamedata = NULL;
    1.21 +	bool debug = false;
    1.22 +
    1.23 +	opterr = 0;
    1.24 +	int opt;
    1.25 +	while ((opt = getopt(argc, argv, "b:de:f:g:")) != -1)
    1.26 +		switch (opt)
    1.27 +		{
    1.28 +			case 'd':
    1.29 +				debug = true;
    1.30 +				break;
    1.31 +			case 'g':
    1.32 +				game = optarg;
    1.33 +				break;
    1.34 +
    1.35 +			case 'e':
    1.36 +				engine = optarg;
    1.37 +				break;
    1.38 +
    1.39 +			case 'f':
    1.40 +				gamedata = optarg;
    1.41 +				break;
    1.42 +
    1.43 +			case 'b':
    1.44 +				binary = optarg;
    1.45 +				break;
    1.46 +
    1.47 +			case '?':
    1.48 +				printf("Usage: ./gdc -g <game> -e <engine> -f <gamedata file> -b <binary>\n");
    1.49 +				return 0;
    1.50 +
    1.51 +			default:
    1.52 +				printf("WHAT\n");
    1.53 +				return 0;
    1.54 +		}
    1.55 +
    1.56 +	if (!game || !engine || !gamedata || !binary)
    1.57 +	{
    1.58 +		printf("Usage: ./gdc -g <game> -e <engine> -f <gamedata file> -b <binary>\n");
    1.59 +		return 0;
    1.60 +	}
    1.61 +
    1.62 +	printf("Game: %s\nEngine: %s\nGamedata: %s\nBinary: %s\n", game, engine, gamedata, binary);
    1.63 +
    1.64 +	void *handle = dlopen(binary, RTLD_LAZY);
    1.65 +	if (!handle)
    1.66 +	{
    1.67 +		printf("Couldn't open %s (%s)\n", binary, dlerror());
    1.68 +		return 0;
    1.69 +	}
    1.70 +
    1.71 +	CGameConfig gc;
    1.72 +	char err[512];
    1.73 +	if (!gc.EnterFile(gamedata, err, sizeof(err)))
    1.74 +	{
    1.75 +		printf("%s: %s\n", gamedata, err);
    1.76 +		return 0;
    1.77 +	}
    1.78 +
    1.79 +	CGameConfig symbols;
    1.80 +	if (!symbols.EnterFile("symbols.txt", err, sizeof(err)))
    1.81 +	{
    1.82 +		printf("symbols.txt: %s\n", err);
    1.83 +		return 0;
    1.84 +	}
    1.85 +
    1.86 +	if (debug)
    1.87 +		for (map<const char*, const char*, cmp_str>::iterator it = symbols.m_Keys.begin(); it != symbols.m_Keys.end(); it++)
    1.88 +			printf("%s - %s\n", it->first, it->second);
    1.89 +
    1.90 +	const char *vtsym = symbols.GetKeyValue("vtsym");
    1.91 +	if (!vtsym)
    1.92 +	{
    1.93 +		printf("Couldn't find vtsym\n");
    1.94 +		return 0;
    1.95 +	}
    1.96 +
    1.97 +#if 0
    1.98 +	void *lolwhat = (void*)1;
    1.99 +	void *handle = lolwhat;
   1.100 +	handle = dlopen(binary, RTLD_LAZY);
   1.101 +	if (!handle)
   1.102 +	{
   1.103 +		printf("Couldn't open %s\n", binary);
   1.104 +		return 0;
   1.105 +	}
   1.106 +#endif
   1.107 +
   1.108 +	void **vt = (void**) mu.ResolveSymbol(handle, vtsym);
   1.109 +	if (!vt)
   1.110 +	{
   1.111 +		printf("Couldn't find vtable %s\n", vtsym);
   1.112 +		dlclose(handle);
   1.113 +		return 0;
   1.114 +	}
   1.115 +
   1.116 +
   1.117 +	for (list<Offset>::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++)
   1.118 +	{
   1.119 +		if (debug) printf("DEBUG %s - l: %d w: %d\n", it->name, it->lin, it->win);
   1.120 +//		else
   1.121 +		{
   1.122 +			const char *symbol = symbols.GetKeyValue(it->name);
   1.123 +			if (symbol)
   1.124 +			{
   1.125 +				int offset = findVFunc(handle, vt, symbol);
   1.126 +
   1.127 +				if (offset == it->lin) printf("%s - good\n", it->name);
   1.128 +				else printf("%s - l: %d w: %d\n", it->name, offset, offset + it->lin - it->win);
   1.129 +			}
   1.130 +			else printf("%s - no Linux symbol, skipping\n", it->name);
   1.131 +		}
   1.132 +	}
   1.133 +
   1.134 +	printf("\nWindows offsets are wild guesses!\n\n");
   1.135 +
   1.136 +	for (list<Sig>::iterator it = gc.m_Sigs.begin(); it != gc.m_Sigs.end(); it++)
   1.137 +	{
   1.138 +		if (debug) printf("DEBUG %s - %s - l: %s\n", it->name, it->lib == Server ? "server" : "engine", it->lin);
   1.139 +//		else
   1.140 +		{
   1.141 +			if (it->lib != Server)
   1.142 +			{
   1.143 +				printf("%s - isn't server, skipping\n", it->name);
   1.144 +				continue;
   1.145 +			}
   1.146 +
   1.147 +			const char *symbol = it->lin;
   1.148 +
   1.149 +			if (!symbol) 
   1.150 +			{
   1.151 +				printf("%s - no Linux symbol, skipping\n", it->name);
   1.152 +				continue;
   1.153 +			}
   1.154 +
   1.155 +			if (symbol[0] != '@')
   1.156 +			{
   1.157 +				printf("%s - didn't start with '@', skipping\n", it->name);
   1.158 +				continue;
   1.159 +			}
   1.160 +
   1.161 +			void *addr = mu.ResolveSymbol(handle, symbol + 1);
   1.162 +
   1.163 +			if (addr) printf("%s - good\n", it->name);
   1.164 +			else printf("%s - %s not found\n", it->name, it->lin);
   1.165 +		}
   1.166 +	}
   1.167 +
   1.168 +	return 0;
   1.169 +}
   1.170 +
   1.171 +/* 
   1.172 +   takes a mangled member function symbol and returns the position where the function name and parameters start
   1.173 +   01234567890123456789012345678
   1.174 +   _ZN9CTFPlayer12ForceRespawnEv
   1.175 +                ^13            ^28
   1.176 +*/
   1.177 +void findFuncPos(const char *sym, int &func, int &params)
   1.178 +{
   1.179 +	int i = 0;
   1.180 +	while ((sym[i] < '0') || (sym[i] > '9')) i++;
   1.181 +	int classLen = atoi(sym + i);
   1.182 +	func = i + (int)ceil(log10(classLen)) + classLen;
   1.183 +	int funcLen = atoi(sym + func);
   1.184 +	params = func + (int)ceil(log10(funcLen)) + funcLen;
   1.185 +}
   1.186 +
   1.187 +int findVFunc(void *handle, void **vt, const char *symbol)
   1.188 +{
   1.189 +	int offset = 1;
   1.190 +	//int overloads = 0;
   1.191 +	int funcPos, paramPos;
   1.192 +	findFuncPos(symbol, funcPos, paramPos);
   1.193 +
   1.194 +	for (int i = 0; i < 1000; i++)
   1.195 +	{
   1.196 +		void *pFunc = vt[i];
   1.197 +		const char *s;
   1.198 +
   1.199 +//		Dl_info info;
   1.200 +//		if (!mu.ResolveAddr(pFunc, &info)) continue;
   1.201 +		if (!(s = mu.ResolveAddr(handle, pFunc))) continue;
   1.202 +
   1.203 +//		if ((i > 1) && (strncmp(info.dli_sname, "_ZTI", 4) == 0)) break;
   1.204 +		if ((i > 1) && (strncmp(s, "_ZTI", 4) == 0)) break;
   1.205 +
   1.206 +
   1.207 +		int tempFuncPos, tempParamPos;
   1.208 +//		findFuncPos(info.dli_sname, tempFuncPos, tempParamPos);
   1.209 +		findFuncPos(s, tempFuncPos, tempParamPos);
   1.210 +
   1.211 +#if 0
   1.212 +		if (strncmp(info.dli_sname[tempFuncPos], symbol[funcPos], paramPos - funcPos) == 0)
   1.213 +		{
   1.214 +			overloads++;
   1.215 +			if (firstOverload == -1) firstOverload = i - 1;
   1.216 +			if (strncmp(info.dli_sname[tempParamPos], symbol[paramPos], strlen(symbol) - paramPos) == 0)
   1.217 +			{
   1.218 +				offset = i;
   1.219 +				matchingOverload = overloads;
   1.220 +			}
   1.221 +		}
   1.222 +#else
   1.223 +//		if (strcmp(info.dli_sname + tempFuncPos, symbol + funcPos) == 0)
   1.224 +		if (strcmp(s + tempFuncPos, symbol + funcPos) == 0)
   1.225 +		{
   1.226 +			offset = i;
   1.227 +			break;
   1.228 +		}
   1.229 +#endif
   1.230 +	}
   1.231 +
   1.232 +	return offset - 2;
   1.233 +}
   1.234 +
   1.235 +unsigned int strncopy(char *dest, const char *src, size_t count)
   1.236 +{
   1.237 +	if (!count)
   1.238 +	{
   1.239 +		return 0;
   1.240 +	}
   1.241 +
   1.242 +	char *start = dest;
   1.243 +	while ((*src) && (--count))
   1.244 +	{
   1.245 +		*dest++ = *src++;
   1.246 +	}
   1.247 +	*dest = '\0';
   1.248 +
   1.249 +	return (dest - start);
   1.250 +}
   1.251 +
   1.252 +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
   1.253 +{
   1.254 +	va_list ap;
   1.255 +	va_start(ap, fmt);
   1.256 +	size_t len = vsnprintf(buffer, maxlength, fmt, ap);
   1.257 +	va_end(ap);
   1.258 +
   1.259 +	if (len >= maxlength)
   1.260 +	{
   1.261 +		buffer[maxlength - 1] = '\0';
   1.262 +		return (maxlength - 1);
   1.263 +	}
   1.264 +	else
   1.265 +	{
   1.266 +		return len;
   1.267 +	}
   1.268 +}
   1.269 +