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