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