sourcemod/tools/Vtable scanner/main.cpp
Matt Woodrow 6d4938f6b5 Removed cruft.
--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402302
2008-06-30 02:04:30 +00:00

171 lines
3.2 KiB
C++

#include <stdio.h>
#include <dlfcn.h>
#include "string.h"
#include "malloc.h"
extern "C" char * cplus_demangle(const char *, int);
#define DMGL_PARAMS (1 << 0)
struct VOffset
{
int linux_offset;
int windows_offset;
};
static bool FindVFunc(void *handle, void **vtable, const char* vtable_end, const char *class_function, const char *params, VOffset *offsets);
int main(int argc, char **argv)
{
void *handle;
void **pVtable;
handle = dlopen(argv[1], RTLD_NOW);
VOffset offsets;
char *params = NULL;
bool ret;
if (argc < 4)
{
fprintf(stderr, "Usage: <binary> <vtable start symbol> <function> <optional: params> <optional: vtable end symbol>\n");
return -1;
}
if (handle == NULL)
{
printf("Failed to open server image, error [%s]\n", dlerror());
return -1;
}
pVtable = (void **)dlsym(handle, argv[2]);
if (argc >= 5)
{
params = argv[4];
if (params[0] == '"')
{
params++;
}
int len = strlen(params)-1;
if (params[len] == '"')
{
params[len] = '\0';
}
if (params[0] == 0)
{
params = NULL;
}
}
if (argc == 6)
{
ret = FindVFunc(handle, pVtable, argv[5], argv[3], params, &offsets);
}
else
{
ret = FindVFunc(handle, pVtable, "_ZTI", argv[3], params, &offsets);
}
if (ret)
{
printf("%s - Win: %i Linux : %i\n", argv[3], offsets.windows_offset, offsets.linux_offset);
return 0;
}
fprintf(stderr, "Failed to find function!");
return -1;
}
static bool FindVFunc(void *handle, void **vtable, const char* vtable_end, const char *class_function, const char *params, VOffset *offsets)
{
Dl_info d;
int linux_offset = -1;
int windows_offset = -1;
int overloads = 0;
int location = 0;
int start_offset = -1;
for (int i=0; i< 1000; i++)
{
void *FuncPtr = vtable[i];
int status = dladdr(FuncPtr, &d);
if (!status)
{
continue;
}
if (i > 1 && strncmp(d.dli_sname, vtable_end, strlen(vtable_end)) == 0)
{
break;
}
char *name = cplus_demangle(d.dli_sname, DMGL_PARAMS);
if (name == NULL)
{
printf("Demangling failed\n");
continue;
}
char *foundfunction = strpbrk(name, ":");
if (foundfunction == NULL)
{
//printf("Couldnt split function\n");
free(name);
continue;
}
//Skip both ':' chars
foundfunction += 2;
if (strncmp(foundfunction, class_function, strlen(class_function)) == 0 && foundfunction[strlen(class_function)] == '(')
{
//printf("Symbol: %s Demangled: %s Offset: %i\n", d.dli_sname, name, i);
//We have a pointer to a function, but it may be overloaded.
overloads++;
if (start_offset == -1)
{
start_offset = i-1;
}
char *foundparams = strpbrk(foundfunction, "(");
if (foundparams == NULL)
{
printf("ARGH\n");
free(name);
continue;
}
if(params == NULL || strcmp(foundparams, params) == 0)
{
//This is actually our function - So this is the linux offset
linux_offset = i;
location = overloads;
}
}
free(name);
}
windows_offset = (overloads-location) + start_offset;
dlclose(handle);
offsets->linux_offset = linux_offset - 2;
offsets->windows_offset = windows_offset - 2;
return true;
}