tools/vtable_scanner/main.cpp
author Asher Baker <asherkin@gmail.com>
Thu Jul 18 17:59:24 2013 -0400 (2013-07-18)
changeset 3952 4c9e2b1cf78d
parent 2677 f6097a2d9812
permissions -rw-r--r--
Fixed inaccurate compiler error when ternary operator is involved (bug 5711, r=dvander).
fyrenmoo@2677
     1
#include <stdio.h>
fyrenmoo@2677
     2
#include <dlfcn.h>
fyrenmoo@2677
     3
#include "string.h"
fyrenmoo@2677
     4
#include "malloc.h"
fyrenmoo@2677
     5
fyrenmoo@2677
     6
extern "C" char * cplus_demangle(const char *, int);
fyrenmoo@2677
     7
#define DMGL_PARAMS	 (1 << 0)
fyrenmoo@2677
     8
fyrenmoo@2677
     9
struct VOffset
fyrenmoo@2677
    10
{
fyrenmoo@2677
    11
	int linux_offset;
fyrenmoo@2677
    12
	int windows_offset;
fyrenmoo@2677
    13
};
fyrenmoo@2677
    14
fyrenmoo@2677
    15
static bool FindVFunc(void *handle, void **vtable, const char* vtable_end, const char *class_function, const char *params, VOffset *offsets);
dvander@2250
    16
dvander@2250
    17
int main(int argc, char **argv)
dvander@2250
    18
{
dvander@2250
    19
	void *handle;
dvander@2250
    20
	void **pVtable;
dvander@2250
    21
dvander@2250
    22
	VOffset offsets;
dvander@2250
    23
	char *params = NULL;
dvander@2250
    24
	bool ret;
dvander@2250
    25
dvander@2250
    26
	if (argc < 4)
dvander@2250
    27
	{
dvander@2250
    28
		fprintf(stderr, "Usage: <binary> <vtable start symbol> <function> <optional: params> <optional: vtable end symbol>\n");
dvander@2250
    29
		return -1;
dvander@2250
    30
	}
dvander@2250
    31
pred@2464
    32
	handle = dlopen(argv[1], RTLD_NOW);
pred@2464
    33
dvander@2250
    34
	if (handle == NULL)
dvander@2250
    35
	{
dvander@2250
    36
		fprintf(stderr, "Failed to open server image, error [%s]\n", dlerror());
dvander@2250
    37
		return -1;
dvander@2250
    38
	}
dvander@2250
    39
dvander@2250
    40
	pVtable = (void **)dlsym(handle, argv[2]);
dvander@2250
    41
dvander@2250
    42
	if (pVtable == NULL)
dvander@2250
    43
	{
fyrenmoo@2677
    44
		char startSym[128];
fyrenmoo@2677
    45
		snprintf(startSym, sizeof(startSym), "_ZTV%d%s", strlen(argv[2]), argv[2]);
fyrenmoo@2677
    46
		pVtable = (void **)dlsym(handle, startSym);
fyrenmoo@2677
    47
	}
fyrenmoo@2677
    48
fyrenmoo@2677
    49
	if (pVtable == NULL)
fyrenmoo@2677
    50
	{
dvander@2250
    51
		fprintf(stderr, "Invalid vtable symbol \"%s\"\n", argv[2]);
pred@2464
    52
		dlclose(handle);
dvander@2250
    53
		return -1;
dvander@2250
    54
	}
dvander@2250
    55
dvander@2250
    56
	if (argc >= 5)
dvander@2250
    57
	{
dvander@2250
    58
		params = argv[4];
dvander@2250
    59
dvander@2250
    60
		if (params[0] == '"')
dvander@2250
    61
		{
dvander@2250
    62
			params++;
dvander@2250
    63
		}
dvander@2250
    64
dvander@2250
    65
		int len = strlen(params)-1;
dvander@2250
    66
dvander@2250
    67
		if (params[len] == '"')
dvander@2250
    68
		{
dvander@2250
    69
			params[len] = '\0';
dvander@2250
    70
		}
dvander@2250
    71
dvander@2250
    72
		if (params[0] == 0)
dvander@2250
    73
		{
dvander@2250
    74
			params = NULL;
dvander@2250
    75
		}
dvander@2250
    76
	}
dvander@2250
    77
dvander@2250
    78
	if (argc == 6)
dvander@2250
    79
	{
dvander@2250
    80
		ret = FindVFunc(handle, pVtable, argv[5], argv[3], params, &offsets);
dvander@2250
    81
	}
dvander@2250
    82
	else
dvander@2250
    83
	{
dvander@2250
    84
		ret = FindVFunc(handle, pVtable, "_ZTI", argv[3], params, &offsets);
dvander@2250
    85
	}
dvander@2250
    86
dvander@2250
    87
	if (ret)
dvander@2250
    88
	{
dvander@2250
    89
		if (params != NULL)
dvander@2250
    90
		{
dvander@2250
    91
			printf("%s%s - Win: %i  Linux : %i\n", argv[3], params, offsets.windows_offset, offsets.linux_offset);
dvander@2250
    92
		}
dvander@2250
    93
		else
dvander@2250
    94
		{
dvander@2250
    95
			printf("%s - Win: %i  Linux : %i\n", argv[3], offsets.windows_offset, offsets.linux_offset);
dvander@2250
    96
		}
dvander@2250
    97
		
pred@2464
    98
		dlclose(handle);
dvander@2250
    99
		return 0;
dvander@2250
   100
	}
dvander@2250
   101
dvander@2250
   102
	fprintf(stderr, "Failed to find function!");
pred@2464
   103
	dlclose(handle);
dvander@2250
   104
	return -1;
dvander@2250
   105
}
fyrenmoo@2677
   106
fyrenmoo@2677
   107
static bool FindVFunc(void *handle, void **vtable, const char* vtable_end, const char *class_function, const char *params, VOffset *offsets)
fyrenmoo@2677
   108
{
fyrenmoo@2677
   109
	Dl_info d;
fyrenmoo@2677
   110
fyrenmoo@2677
   111
	int linux_offset = -1;
fyrenmoo@2677
   112
	int windows_offset = -1;
fyrenmoo@2677
   113
fyrenmoo@2677
   114
	int overloads = 0;
fyrenmoo@2677
   115
	int location = 0;
fyrenmoo@2677
   116
	int start_offset = -1;
fyrenmoo@2677
   117
fyrenmoo@2677
   118
	for (int i=0; i< 1000; i++)
fyrenmoo@2677
   119
	{
fyrenmoo@2677
   120
		void *FuncPtr = vtable[i];
fyrenmoo@2677
   121
fyrenmoo@2677
   122
		int status = dladdr(FuncPtr, &d);
fyrenmoo@2677
   123
fyrenmoo@2677
   124
		if (!status)
fyrenmoo@2677
   125
		{
fyrenmoo@2677
   126
			continue;
fyrenmoo@2677
   127
		}
fyrenmoo@2677
   128
fyrenmoo@2677
   129
		if (i > 1 && strncmp(d.dli_sname, vtable_end, strlen(vtable_end)) == 0)
fyrenmoo@2677
   130
		{
fyrenmoo@2677
   131
			break;
fyrenmoo@2677
   132
		}
fyrenmoo@2677
   133
fyrenmoo@2677
   134
		char *name = cplus_demangle(d.dli_sname, DMGL_PARAMS);
fyrenmoo@2677
   135
fyrenmoo@2677
   136
		if (name == NULL)
fyrenmoo@2677
   137
		{
fyrenmoo@2677
   138
			printf("Demangling failed\n");
fyrenmoo@2677
   139
			continue;
fyrenmoo@2677
   140
		}
fyrenmoo@2677
   141
fyrenmoo@2677
   142
		char *foundfunction = strpbrk(name, ":");
fyrenmoo@2677
   143
fyrenmoo@2677
   144
		if (foundfunction == NULL)
fyrenmoo@2677
   145
		{
fyrenmoo@2677
   146
			//printf("Couldnt split function\n");
fyrenmoo@2677
   147
			free(name);
fyrenmoo@2677
   148
			continue;
fyrenmoo@2677
   149
		}
fyrenmoo@2677
   150
fyrenmoo@2677
   151
		//Skip both ':' chars
fyrenmoo@2677
   152
		foundfunction += 2;
fyrenmoo@2677
   153
fyrenmoo@2677
   154
fyrenmoo@2677
   155
		if (strncmp(foundfunction, class_function, strlen(class_function)) == 0 && foundfunction[strlen(class_function)] == '(')
fyrenmoo@2677
   156
		{
fyrenmoo@2677
   157
			//printf("Symbol: %s Demangled: %s Offset: %i\n", d.dli_sname, name, i);
fyrenmoo@2677
   158
fyrenmoo@2677
   159
			//We have a pointer to a function, but it may be overloaded.
fyrenmoo@2677
   160
			overloads++;
fyrenmoo@2677
   161
fyrenmoo@2677
   162
			if (start_offset == -1)
fyrenmoo@2677
   163
			{
fyrenmoo@2677
   164
				start_offset = i-1;
fyrenmoo@2677
   165
			}
fyrenmoo@2677
   166
fyrenmoo@2677
   167
			char *foundparams = strpbrk(foundfunction, "(");
fyrenmoo@2677
   168
fyrenmoo@2677
   169
			if (foundparams == NULL)
fyrenmoo@2677
   170
			{
fyrenmoo@2677
   171
				printf("ARGH\n");
fyrenmoo@2677
   172
				free(name);
fyrenmoo@2677
   173
				continue;
fyrenmoo@2677
   174
			}
fyrenmoo@2677
   175
fyrenmoo@2677
   176
			if(params == NULL || strcmp(foundparams, params) == 0)
fyrenmoo@2677
   177
			{
fyrenmoo@2677
   178
				//This is actually our function - So this is the linux offset
fyrenmoo@2677
   179
				linux_offset = i;
fyrenmoo@2677
   180
				location = overloads;
fyrenmoo@2677
   181
			}
fyrenmoo@2677
   182
		}
fyrenmoo@2677
   183
fyrenmoo@2677
   184
		free(name);
fyrenmoo@2677
   185
	}
fyrenmoo@2677
   186
fyrenmoo@2677
   187
	windows_offset = (overloads-location) + start_offset;
fyrenmoo@2677
   188
fyrenmoo@2677
   189
	offsets->linux_offset = linux_offset - 2;
fyrenmoo@2677
   190
	offsets->windows_offset = windows_offset - 2;
fyrenmoo@2677
   191
fyrenmoo@2677
   192
	return true;
fyrenmoo@2677
   193
}