diff --git a/tools/Vtable scanner/Makefile b/tools/Vtable scanner/Makefile new file mode 100644 index 00000000..de2d7323 --- /dev/null +++ b/tools/Vtable scanner/Makefile @@ -0,0 +1,76 @@ +# (C)2004-2008 SourceMod Development Team +# Makefile written by David "BAILOPAN" Anderson + + +##################################### +### EDIT BELOW FOR OTHER PROJECTS ### +##################################### + +OBJECTS = main.cpp + +############################################## +### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### +############################################## + +C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing +C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3 +C_GCC4_FLAGS = -fvisibility=hidden +CPP_GCC4_FLAGS = -fvisibility-inlines-hidden +CPP = gcc-4.1 + +BINARY = vtablecheck + +LINK += -L. -liberty -ldl + +INCLUDE += -I. + +CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \ + -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \ + -Wno-uninitialized -mfpmath=sse -msse -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32 +CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti + +################################################ +### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### +################################################ + +ifeq "$(DEBUG)" "true" + BIN_DIR = Debug + CFLAGS += $(C_DEBUG_FLAGS) +else + BIN_DIR = Release + CFLAGS += $(C_OPT_FLAGS) +endif + +GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) +ifeq "$(GCC_VERSION)" "4" + CFLAGS += $(C_GCC4_FLAGS) + CPPFLAGS += $(CPP_GCC4_FLAGS) +endif + +OBJ_LINUX := $(OBJECTS:%vm_engine.cpp=$(BIN_DIR)/%vm_engine.o) +OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o) +OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o) + +$(BIN_DIR)/%vm_engine.o: %vm_engine.cpp + $(CPP) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +$(BIN_DIR)/%.o: %.cpp + $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +$(BIN_DIR)/%.o: %.c + $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< + +all: + mkdir -p $(BIN_DIR) + $(MAKE) -f Makefile sourcemod + +sourcemod: $(OBJ_LINUX) + $(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -o$(BIN_DIR)/$(BINARY) + +debug: + $(MAKE) -f Makefile all DEBUG=true + +default: all + +clean: + rm -rf $(BIN_DIR)/$(BINARY) diff --git a/tools/Vtable scanner/libiberty.a b/tools/Vtable scanner/libiberty.a new file mode 100644 index 00000000..00a38036 Binary files /dev/null and b/tools/Vtable scanner/libiberty.a differ diff --git a/tools/Vtable scanner/main.cpp b/tools/Vtable scanner/main.cpp new file mode 100644 index 00000000..c3e96a50 --- /dev/null +++ b/tools/Vtable scanner/main.cpp @@ -0,0 +1,192 @@ +#include +#include +#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: \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; + +#if 0 + if (FindVFunc(handle, pVtable, "CommitSuicide", "(bool, bool)", &offsets)) + printf("Commit Suicide - Win: %i Linux : %i\n", offsets.windows_offset, offsets.linux_offset); + + if (FindVFunc(handle, pVtable, "KeyValue", "(char const*, char const*)", &offsets)) + printf("KeyValue - Win: %i Linux : %i\n", offsets.windows_offset, offsets.linux_offset); + + if (FindVFunc(handle, pVtable, "KeyValue", "(char const*, float)", &offsets)) + printf("KeyValue Float - Win: %i Linux : %i\n", offsets.windows_offset, offsets.linux_offset); + + if (FindVFunc(handle, handle, pVtable, "KeyValue", "(char const*, Vector const&)", &offsets)) + printf("KeyValue Vector - Win: %i Linux : %i\n", offsets.windows_offset, offsets.linux_offset); + + if (FindVFunc(handle, pVtable, "Ignite", NULL, &offsets)) + printf("Ignite - Win: %i Linux : %i\n", offsets.windows_offset, offsets.linux_offset); + + if (FindVFunc(handle, pVtable, "Extinguish", NULL, &offsets)) + printf("Extinguish - Win: %i Linux : %i\n", offsets.windows_offset, offsets.linux_offset); + + return 0; +#endif +} + +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; +} diff --git a/tools/Vtable scanner/tfscan.sh b/tools/Vtable scanner/tfscan.sh new file mode 100644 index 00000000..cbe22b25 --- /dev/null +++ b/tools/Vtable scanner/tfscan.sh @@ -0,0 +1,17 @@ +echo "sdktools.games.ep2.txt +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer RemovePlayerItem +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer Weapon_GetSlot +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer Ignite +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer Extinguish +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer Teleport +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer CommitSuicide "(bool, bool)" +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer GetVelocity +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer EyeAngles +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer KeyValue "(char const*, char const*)" +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer KeyValue "(char const*, float)" +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer KeyValue "(char const*, Vector const&)" +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer SetModel +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer AcceptInput +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer Activate +echo "sm-tf2.games.txt" +./vtablecheck ~/srcds/orangebox/tf/bin/server_i486.so _ZTV9CTFPlayer ForceRespawn