diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/common/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/common/Makefile.in | 2 | ||||
-rw-r--r-- | src/common/core.c | 5 | ||||
-rw-r--r-- | src/common/plugin.h | 86 | ||||
-rw-r--r-- | src/common/plugins.c | 415 | ||||
-rw-r--r-- | src/common/plugins.h | 69 | ||||
-rw-r--r-- | src/plugins/CMakeLists.txt | 174 | ||||
-rw-r--r-- | src/plugins/Makefile.in | 54 | ||||
-rw-r--r-- | src/plugins/console.c | 496 | ||||
-rw-r--r-- | src/plugins/console.def | 13 | ||||
-rw-r--r-- | src/plugins/dbghelpplug.c | 1896 | ||||
-rw-r--r-- | src/plugins/dbghelpplug.rc | 54 | ||||
-rw-r--r-- | src/plugins/pid.c | 53 | ||||
-rw-r--r-- | src/plugins/pid.def | 7 | ||||
-rw-r--r-- | src/plugins/sample.c | 77 | ||||
-rw-r--r-- | src/plugins/sample.def | 11 | ||||
-rw-r--r-- | src/plugins/sig.c | 208 |
18 files changed, 1 insertions, 3623 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0c120f99a..94ccf4183 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,4 +17,3 @@ add_subdirectory( login ) add_subdirectory( char ) add_subdirectory( map ) add_subdirectory( tool ) -add_subdirectory( plugins ) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index effd0b2ab..6be5f170a 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -31,7 +31,6 @@ set( COMMON_ALL_HEADERS "${CMAKE_CURRENT_BINARY_DIR}/svnversion.h" "${COMMON_SOURCE_DIR}/cbasetypes.h" "${COMMON_SOURCE_DIR}/mmo.h" - "${COMMON_SOURCE_DIR}/plugin.h" ) set( COMMON_MINI_HEADERS @@ -71,7 +70,6 @@ set( COMMON_BASE_HEADERS "${COMMON_SOURCE_DIR}/mapindex.h" "${COMMON_SOURCE_DIR}/md5calc.h" "${COMMON_SOURCE_DIR}/nullpo.h" - "${COMMON_SOURCE_DIR}/plugins.h" "${COMMON_SOURCE_DIR}/random.h" "${COMMON_SOURCE_DIR}/showmsg.h" "${COMMON_SOURCE_DIR}/socket.h" @@ -92,7 +90,6 @@ set( COMMON_BASE_SOURCES "${COMMON_SOURCE_DIR}/mapindex.c" "${COMMON_SOURCE_DIR}/md5calc.c" "${COMMON_SOURCE_DIR}/nullpo.c" - "${COMMON_SOURCE_DIR}/plugins.c" "${COMMON_SOURCE_DIR}/random.c" "${COMMON_SOURCE_DIR}/showmsg.c" "${COMMON_SOURCE_DIR}/socket.c" diff --git a/src/common/Makefile.in b/src/common/Makefile.in index 5e3b00a88..c778ff17b 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -1,5 +1,5 @@ -COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/plugins.o obj_all/lock.o \ +COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/lock.o \ obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \ obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \ obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \ diff --git a/src/common/core.c b/src/common/core.c index 37e5fc562..bde1d9c0b 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -9,7 +9,6 @@ #include "../common/db.h" #include "../common/socket.h" #include "../common/timer.h" -#include "../common/plugins.h" #endif #include <stdio.h> @@ -288,10 +287,8 @@ int main (int argc, char **argv) timer_init(); socket_init(); - plugins_init(); do_init(argc,argv); - plugin_event_trigger(EVENT_ATHENA_INIT); {// Main runtime cycle int next; @@ -301,11 +298,9 @@ int main (int argc, char **argv) } } - plugin_event_trigger(EVENT_ATHENA_FINAL); do_final(); timer_final(); - plugins_final(); socket_final(); db_final(); #endif diff --git a/src/common/plugin.h b/src/common/plugin.h deleted file mode 100644 index ec6399c57..000000000 --- a/src/common/plugin.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _PLUGIN_H_ -#define _PLUGIN_H_ - -#include "../common/cbasetypes.h" - -////// Plugin functions /////////////// - -// Plugin version <major version>.<minor version> -// * <major version> is increased and <minor version> reset when at least one -// export of the previous version becomes incompatible -// * <minor version> is increased if the previous version remains compatible -// -// Compatible plugins have: -// - equal major version -// - lower or equal minor version -#define PLUGIN_VERSION "1.03" - -typedef struct _Plugin_Info { - char* name; - char type; - char* version; - char* req_version; - char* description; -} Plugin_Info; - -typedef struct _Plugin_Event_Table { - char* func_name; - char* event_name; -} Plugin_Event_Table; - -// Format of the test function -typedef int Plugin_Test_Func(void); -#define EVENT_PLUGIN_INIT "Plugin_Init" // Initialize the plugin -#define EVENT_PLUGIN_FINAL "Plugin_Final" // Finalize the plugin -#define EVENT_ATHENA_INIT "Athena_Init" // Server started -#define EVENT_ATHENA_FINAL "Athena_Final" // Server ended - -// Format of event functions -typedef void Plugin_Event_Func(void); -#define EVENT_PLUGIN_TEST "Plugin_Test" // Test the plugin for compatibility - -////// Plugin Export functions ///////////// - -#define PLUGIN_ALL 0 -#define PLUGIN_LOGIN 1 -#define PLUGIN_CHAR 2 -#define PLUGIN_MAP 8 -#define PLUGIN_CORE 16 - -#define IMPORT_SYMBOL(s,n) SET_FUNCPOINTER((s), plugin_call_table[n]) - -#define SYMBOL_SERVER_TYPE 0 -#define SYMBOL_SERVER_NAME 1 -#define SYMBOL_ARG_C 2 -#define SYMBOL_ARG_V 3 -#define SYMBOL_RUNFLAG 4 -#define SYMBOL_GETTICK 5 -#define SYMBOL_GET_SVN_REVISION 6 -#define SYMBOL_ADD_TIMER 7 -#define SYMBOL_ADD_TIMER_INTERVAL 8 -#define SYMBOL_ADD_TIMER_FUNC_LIST 9 -#define SYMBOL_DELETE_TIMER 10 -#define SYMBOL_GET_UPTIME 11 -#define SYMBOL_ADDR 12 -#define SYMBOL_FD_MAX 13 -#define SYMBOL_SESSION 14 -#define SYMBOL_DELETE_SESSION 15 -#define SYMBOL_WFIFOSET 16 -#define SYMBOL_RFIFOSKIP 17 -#define SYMBOL_FUNC_PARSE_TABLE 18 -// 1.03 -#define SYMBOL_PARSE_CONSOLE 19 - -////// Global Plugin variables ///////////// - -#define PLUGIN_INFO struct _Plugin_Info plugin_info -#define PLUGIN_EVENTS_TABLE struct _Plugin_Event_Table plugin_event_table[] - -#ifndef _PLUGINS_H_ -void** plugin_call_table; -#endif - -#endif /* _PLUGIN_H_ */ diff --git a/src/common/plugins.c b/src/common/plugins.c deleted file mode 100644 index 5e021f35e..000000000 --- a/src/common/plugins.c +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#include "../common/mmo.h" -#include "../common/core.h" -#include "../common/timer.h" -#include "../common/utils.h" // findfile() -#include "../common/socket.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "plugins.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifndef WIN32 -#include <unistd.h> -#endif - -////////////////////////////////////////////// - -typedef struct _Plugin_Event { - struct _Plugin_Event* next; - Plugin_Event_Func* func; -} Plugin_Event; - -typedef struct _Plugin_Event_List { - struct _Plugin_Event_List* next; - char* name; - struct _Plugin_Event* events; -} Plugin_Event_List; - -static int auto_search = 0; -static int load_priority = 0; -Plugin_Event_List* event_head = NULL; -Plugin* plugin_head = NULL; - -static Plugin_Info default_info = { "Unknown", PLUGIN_ALL, "0", PLUGIN_VERSION, "Unknown" }; - -void** plugin_call_table; -static size_t call_table_size = 0; -static size_t max_call_table = 0; - -////// Plugin Events Functions ////////////////// - -int register_plugin_func(char* name) -{ - Plugin_Event_List* evl; - if( name ){ - //ShowDebug("register_plugin_func(%s)\n", name); - CREATE(evl, Plugin_Event_List, 1); - evl->next = event_head; - evl->name = aStrdup(name); - evl->events = NULL; - event_head = evl; - } - return 0; -} - -static Plugin_Event_List* search_plugin_func(char* name) -{ - Plugin_Event_List* evl = event_head; - while( evl ){ - if( strcmpi(evl->name,name) == 0 ) - return evl; - evl = evl->next; - } - return NULL; -} - -int register_plugin_event(Plugin_Event_Func* func, char* name) -{ - Plugin_Event_List* evl = search_plugin_func(name); - //ShowDebug("register_plugin_event(0x%x, %s)\n", func, name); - if( !evl ) - {// event does not exist, register - register_plugin_func(name); - // get the new event list - evl = search_plugin_func(name); - } - if( evl ){ - Plugin_Event* ev; - - CREATE(ev, Plugin_Event, 1); - ev->func = func; - ev->next = NULL; - - // insert event at the end of the linked list - if( evl->events == NULL ) - evl->events = ev; - else { - Plugin_Event* last_ev = evl->events; - while( last_ev ){ - if( last_ev->next == NULL ){ - last_ev->next = ev; - break; - } - last_ev = last_ev->next; - } - } - } - return 0; -} - -int plugin_event_trigger(char* name) -{ - int c = 0; - Plugin_Event_List* evl = search_plugin_func(name); - //ShowDebug("plugin_event_trigger(%s)\n", name); - if( evl ){ - Plugin_Event* ev = evl->events; - while( ev ){ - ev->func(); - //ShowDebug("plugin_event_trigger: Executing function 0x%x.\n", ev->func); - ev = ev->next; - ++c; - } - } - return c; -} - -////// Plugins Call Table Functions ///////// - -int export_symbol(void* var, size_t offset) -{ - //ShowDebug("export_symbol(0x%x,%d)\n", var,offset); - - // add to the end of the list - if( offset < 0 ) - offset = call_table_size; - - if( offset >= max_call_table ) - {// realloc if not large enough - max_call_table = 1 + offset; - RECREATE(plugin_call_table, void*, max_call_table); - - // clear the new alloced block - memset(plugin_call_table + call_table_size, 0, (max_call_table-call_table_size)*sizeof(void*)); - } - - // the new table size is delimited by the new element at the end - if( offset >= call_table_size ) - call_table_size = offset+1; - - // put the pointer at the selected place - plugin_call_table[offset] = var; - return 0; -} - -////// Plugins Core ///////////////////////// - -static int plugin_iscompatible(char* version) -{ - int req_major = 0; - int req_minor = 0; - int major = 0; - int minor = 0; - - if( version == NULL ) - return 0; - sscanf(version, "%d.%d", &req_major, &req_minor); - sscanf(PLUGIN_VERSION, "%d.%d", &major, &minor); - return ( req_major == major && req_minor <= minor ); -} - -Plugin* plugin_open(const char* filename) -{ - Plugin* plugin; - Plugin_Info* info; - Plugin_Event_Table* events; - void** procs; - int init_flag = 1; - - //ShowDebug("plugin_open(%s)\n", filename); - - // Check if the plugin has been loaded before - plugin = plugin_head; - while (plugin) { - // returns handle to the already loaded plugin - if( plugin->state && strcmpi(plugin->filename, filename) == 0 ){ - ShowWarning("plugin_open: not loaded (duplicate) : '"CL_WHITE"%s"CL_RESET"'\n", filename); - return plugin; - } - plugin = plugin->next; - } - - CREATE(plugin, Plugin, 1); - plugin->state = -1; // not loaded - - plugin->dll = DLL_OPEN(filename); - if( !plugin->dll ){ - ShowWarning("plugin_open: not loaded (invalid file) : '"CL_WHITE"%s"CL_RESET"'\n", filename); - plugin_unload(plugin); - return NULL; - } - - // Retrieve plugin information - plugin->state = 0; // initialising - info = (Plugin_Info*)DLL_SYM(plugin->dll, "plugin_info"); - // For high priority plugins (those that are explicitly loaded from the conf file) - // we'll ignore them even (could be a 3rd party dll file) - if( !info ) - {// foreign plugin - //ShowDebug("plugin_open: plugin_info not found\n"); - if( load_priority == 0 ) - {// not requested - //ShowDebug("plugin_open: not loaded (not requested) : '"CL_WHITE"%s"CL_RESET"'\n", filename); - plugin_unload(plugin); - return NULL; - } - } else if( !plugin_iscompatible(info->req_version) ) - {// incompatible version - ShowWarning("plugin_open: not loaded (incompatible version '%s' -> '%s') : '"CL_WHITE"%s"CL_RESET"'\n", info->req_version, PLUGIN_VERSION, filename); - plugin_unload(plugin); - return NULL; - } else if( (info->type != PLUGIN_ALL && info->type != PLUGIN_CORE && info->type != SERVER_TYPE) || - (info->type == PLUGIN_CORE && SERVER_TYPE != PLUGIN_LOGIN && SERVER_TYPE != PLUGIN_CHAR && SERVER_TYPE != PLUGIN_MAP) ) - {// not for this server - //ShowDebug("plugin_open: not loaded (incompatible) : '"CL_WHITE"%s"CL_RESET"'\n", filename); - plugin_unload(plugin); - return NULL; - } - - plugin->info = ( info != NULL ? info : &default_info ); - plugin->filename = aStrdup(filename); - - // Initialise plugin call table (For exporting procedures) - procs = (void**)DLL_SYM(plugin->dll, "plugin_call_table"); - if( procs ) - *procs = plugin_call_table; - //else ShowDebug("plugin_open: plugin_call_table not found\n"); - - // Register plugin events - events = (Plugin_Event_Table*)DLL_SYM(plugin->dll, "plugin_event_table"); - if( events ){ - int i = 0; - //ShowDebug("plugin_open: parsing plugin_event_table\n"); - while( events[i].func_name ){ - if( strcmpi(events[i].event_name, EVENT_PLUGIN_TEST) == 0 ){ - Plugin_Test_Func* test_func; - test_func = (Plugin_Test_Func*)DLL_SYM(plugin->dll, events[i].func_name); - //ShowDebug("plugin_open: invoking "EVENT_PLUGIN_TEST" with %s()\n", events[i].func_name); - if( test_func && test_func() == 0 ){ - // plugin has failed test, disabling - //ShowDebug("plugin_open: disabled (failed test) : %s\n", filename); - init_flag = 0; - } - } else { - Plugin_Event_Func* func; - func = (Plugin_Event_Func*)DLL_SYM(plugin->dll, events[i].func_name); - if (func) - register_plugin_event(func, events[i].event_name); - else - ShowError("Failed to locate function '%s' in '%s'.\n", events[i].func_name, filename); - } - i++; - } - } - //else ShowDebug("plugin_open: plugin_event_table not found\n"); - - plugin->next = plugin_head; - plugin_head = plugin; - - plugin->state = init_flag; // fully loaded - ShowStatus("Done loading plugin '"CL_WHITE"%s"CL_RESET"'\n", (info) ? plugin->info->name : filename); - - return plugin; -} - -void plugin_load(const char* filename) -{ - plugin_open(filename); -} - -void plugin_unload(Plugin* plugin) -{ - if( plugin == NULL ) - return; - if( plugin->filename ) - aFree(plugin->filename); - if( plugin->dll ) - DLL_CLOSE(plugin->dll); - aFree(plugin); -} - -#ifdef WIN32 -char *DLL_ERROR(void) -{ - static char dllbuf[80]; - DWORD dw = GetLastError(); - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, 0, dllbuf, 80, NULL); - return dllbuf; -} -#endif - -////// Initialize/Finalize //////////////////// - -static int plugins_config_read(const char *cfgName) -{ - char line[1024], w1[1024], w2[1024]; - FILE *fp; - - fp = fopen(cfgName, "r"); - if( fp == NULL ){ - ShowError("File not found: %s\n", cfgName); - return 1; - } - while( fgets(line, sizeof(line), fp) ) - { - if( line[0] == '/' && line[1] == '/' ) - continue; - if( sscanf(line,"%[^:]: %[^\r\n]",w1,w2) != 2 ) - continue; - - if( strcmpi(w1,"auto_search") == 0 ){ - if( strcmpi(w2,"yes") == 0 ) - auto_search = 1; - else if( strcmpi(w2,"no") == 0 ) - auto_search = 0; - else - auto_search = atoi(w2); - } else if( strcmpi(w1,"plugin") == 0 ){ - char filename[128]; - sprintf(filename, "plugins/%s%s", w2, DLL_EXT); - plugin_load(filename); - } else if( strcmpi(w1,"import") == 0 ) - plugins_config_read(w2); - else - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); - } - fclose(fp); - return 0; -} - -void plugins_init(void) -{ - // Sugested functionality: - // add atcommands/script commands (Borf) - char* PLUGIN_CONF_FILENAME = "conf/plugin_athena.conf"; - //ShowDebug("plugins_init()\n"); - register_plugin_func(EVENT_PLUGIN_INIT); - register_plugin_func(EVENT_PLUGIN_FINAL); - register_plugin_func(EVENT_ATHENA_INIT); - register_plugin_func(EVENT_ATHENA_FINAL); - - // networking - EXPORT_SYMBOL(RFIFOSKIP, SYMBOL_RFIFOSKIP); - EXPORT_SYMBOL(WFIFOSET, SYMBOL_WFIFOSET); - EXPORT_SYMBOL(do_close, SYMBOL_DELETE_SESSION); - EXPORT_SYMBOL(session, SYMBOL_SESSION); - EXPORT_SYMBOL(&fd_max, SYMBOL_FD_MAX); - EXPORT_SYMBOL(addr_, SYMBOL_ADDR); - // timers - EXPORT_SYMBOL(get_uptime, SYMBOL_GET_UPTIME); - EXPORT_SYMBOL(delete_timer, SYMBOL_DELETE_TIMER); - EXPORT_SYMBOL(add_timer_func_list, SYMBOL_ADD_TIMER_FUNC_LIST); - EXPORT_SYMBOL(add_timer_interval, SYMBOL_ADD_TIMER_INTERVAL); - EXPORT_SYMBOL(add_timer, SYMBOL_ADD_TIMER); - EXPORT_SYMBOL((void*)get_svn_revision, SYMBOL_GET_SVN_REVISION); - EXPORT_SYMBOL(gettick, SYMBOL_GETTICK); - // core - EXPORT_SYMBOL(parse_console, SYMBOL_PARSE_CONSOLE); - EXPORT_SYMBOL(&runflag, SYMBOL_RUNFLAG); - EXPORT_SYMBOL(arg_v, SYMBOL_ARG_V); - EXPORT_SYMBOL(&arg_c, SYMBOL_ARG_C); - EXPORT_SYMBOL(SERVER_NAME, SYMBOL_SERVER_NAME); - EXPORT_SYMBOL(&SERVER_TYPE, SYMBOL_SERVER_TYPE); - - load_priority = 1; - plugins_config_read(PLUGIN_CONF_FILENAME); - load_priority = 0; - - if( auto_search ) - findfile("plugins", DLL_EXT, plugin_load); - - plugin_event_trigger(EVENT_PLUGIN_INIT); - - return; -} - -void plugins_final(void) -{ - Plugin* plugin = plugin_head; - Plugin* next_plugin; - Plugin_Event_List* evl = event_head; - Plugin_Event_List* next_evl; - Plugin_Event* ev; - Plugin_Event* next_ev; - - //ShowDebug("plugins_final()\n"); - plugin_event_trigger(EVENT_PLUGIN_FINAL); - - while( plugin ){ - next_plugin = plugin->next; - plugin_unload(plugin); - plugin = next_plugin; - } - - while( evl ){ - ev = evl->events; - while( ev ){ - next_ev = ev->next; - aFree(ev); - ev = next_ev; - } - next_evl = evl->next; - aFree(evl->name); - aFree(evl); - evl = next_evl; - } - - aFree(plugin_call_table); - - return; -} diff --git a/src/common/plugins.h b/src/common/plugins.h deleted file mode 100644 index 8c9c70d9f..000000000 --- a/src/common/plugins.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _PLUGINS_H_ -#define _PLUGINS_H_ - -#include "../common/cbasetypes.h" -#include "../common/plugin.h" - -////// Dynamic Link Library functions /////////////// - -#ifdef WIN32 - - #define WIN32_LEAN_AND_MEAN - #include <windows.h> - #define DLL_OPEN(x) LoadLibraryA(x) - #define DLL_SYM(x,y) GetProcAddress(x,y) - #define DLL_CLOSE(x) FreeLibrary(x) - char *DLL_ERROR(void); - - #define DLL_EXT ".dll" - #define DLL HINSTANCE - -#else - - #include <dlfcn.h> - #define DLL_OPEN(x) dlopen(x,RTLD_NOW) - #define DLL_SYM(x,y) dlsym(x,y) - #define DLL_CLOSE(x) dlclose(x) - #define DLL_ERROR dlerror - - #ifdef CYGWIN - #define DLL_EXT ".dll" - #else - #define DLL_EXT ".so" - #endif - #define DLL void * - - #include <string.h> // size_t - -#endif - -////// Plugin Definitions /////////////////// - -typedef struct _Plugin { - DLL dll; - char state; - char* filename; - struct _Plugin_Info* info; - struct _Plugin* next; -} Plugin; - -///////////////////////////////////////////// - -int register_plugin_func(char* name); -int register_plugin_event(Plugin_Event_Func* func, char* name); -int plugin_event_trigger(char* name); - -int export_symbol(void* var, size_t offset); -#define EXPORT_SYMBOL(s,o) export_symbol((void*)(s),(o)); -#define EXPORT_SYMBOL2(s) EXPORT_SYMBOL((s), -1); - -Plugin* plugin_open(const char* filename); -void plugin_load(const char* filename); -void plugin_unload(Plugin* plugin); -void plugins_init(void); -void plugins_final(void); - -#endif /* _PLUGINS_H_ */ diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt deleted file mode 100644 index 21ffc3994..000000000 --- a/src/plugins/CMakeLists.txt +++ /dev/null @@ -1,174 +0,0 @@ - -# -# setup -# -get_property( CAN_BUILD_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS ) -if( NOT CAN_BUILD_SHARED_LIBS ) - return() -endif() - -# -# console -# -option( BUILD_PLUGIN_console "build console plugin" OFF ) -if( BUILD_PLUGIN_console ) -message( STATUS "Creating target console" ) -set( CONSOLE_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/console.c" - "${CMAKE_CURRENT_SOURCE_DIR}/console.def" - ) -set( LIBRARIES ${GLOBAL_LIBRARIES} ) -set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) -set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) -set( SOURCE_FILES ${CONSOLE_SOURCES} ) -source_group( console FILES ${CONSOLE_SOURCES} ) -include_directories( ${INCLUDE_DIRS} ) -add_library( console SHARED ${SOURCE_FILES} ) -target_link_libraries( console ${LIBRARIES} ) -set_target_properties( console PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) -set_target_properties( console PROPERTIES PREFIX "" ) -if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_console DESCRIPTION "console plugin" DISPLAY_NAME "console" GROUP Runtime ) - install( TARGETS console - DESTINATION "plugins" - COMPONENT Runtime_console ) -endif( INSTALL_COMPONENT_RUNTIME ) -set( TARGET_LIST ${TARGET_LIST} console CACHE INTERNAL "" ) -message( STATUS "Creating target console - done" ) -endif( BUILD_PLUGIN_console ) - - -# -# dbghelpplug -# -if( WIN32 ) - find_path( HAVE_DBGHELP_H dbghelp.h ) - mark_as_advanced( HAVE_DBGHELP_H ) - if( HAVE_DBGHELP_H ) - option( BUILD_PLUGIN_dbghelpplug "build dbghelpplug plugin" OFF ) - endif() -endif() -if( NOT DEFINED BUILD_PLUGIN_dbghelpplug ) - message( STATUS "Disabled dbghelpplug plugin target (requires WIN32 and HAVE_DBGHELP_H)" ) -endif() -if( BUILD_PLUGIN_dbghelpplug ) -message( STATUS "Creating target dbghelpplug" ) -set( DBGHELPPLUG_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/dbghelpplug.c" - "${CMAKE_CURRENT_SOURCE_DIR}/dbghelpplug.rc" - ) -set( LIBRARIES ${GLOBAL_LIBRARIES} ) -set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) -set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) -set( SOURCE_FILES ${DBGHELPPLUG_SOURCES} ) -source_group( dbghelpplug FILES ${DBGHELPPLUG_SOURCES} ) -include_directories( ${INCLUDE_DIRS} ) -add_library( dbghelpplug SHARED ${SOURCE_FILES} ) -target_link_libraries( dbghelpplug ${LIBRARIES} ) -set_target_properties( dbghelpplug PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) -set_target_properties( dbghelpplug PROPERTIES PREFIX "" ) -if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_dbghelpplug DESCRIPTION "dbghelpplug plugin" DISPLAY_NAME "dbghelpplug" GROUP Runtime ) - install( TARGETS dbghelpplug - DESTINATION "plugins" - COMPONENT Runtime_dbghelpplug ) -endif( INSTALL_COMPONENT_RUNTIME ) -set( TARGET_LIST ${TARGET_LIST} dbghelpplug CACHE INTERNAL "" ) -message( STATUS "Creating target dbghelpplug - done" ) -endif( BUILD_PLUGIN_dbghelpplug ) - - -# -# pid -# -if( WIN32 OR HAVE_GETPID ) - option( BUILD_PLUGIN_pid "build pid plugin" OFF ) -else() - message( STATUS "Disabled pid plugin target (requires WIN32 or HAVE_GETPID)" ) -endif() -if( BUILD_PLUGIN_pid ) -message( STATUS "Creating target pid" ) -set( PID_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/pid.c" - "${CMAKE_CURRENT_SOURCE_DIR}/pid.def" - ) -set( LIBRARIES ${GLOBAL_LIBRARIES} ) -set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) -set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) -set( SOURCE_FILES ${PID_SOURCES} ) -source_group( pid FILES ${PID_SOURCES} ) -include_directories( ${INCLUDE_DIRS} ) -add_library( pid SHARED ${SOURCE_FILES} ) -target_link_libraries( pid ${LIBRARIES} ) -set_target_properties( pid PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) -set_target_properties( pid PROPERTIES PREFIX "" ) -if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_pid DESCRIPTION "pid plugin" DISPLAY_NAME "pid" GROUP Runtime ) - install( TARGETS pid - DESTINATION "plugins" - COMPONENT Runtime_pid ) -endif( INSTALL_COMPONENT_RUNTIME ) -set( TARGET_LIST ${TARGET_LIST} pid CACHE INTERNAL "" ) -message( STATUS "Creating target pid - done" ) -endif( BUILD_PLUGIN_pid ) - - -# -# sample -# -option( BUILD_PLUGIN_sample "build sample plugin" OFF ) -if( BUILD_PLUGIN_sample ) -message( STATUS "Creating target sample" ) -set( SAMPLE_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/sample.c" - "${CMAKE_CURRENT_SOURCE_DIR}/sample.def" - ) -set( LIBRARIES ${GLOBAL_LIBRARIES} ) -set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) -set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) -set( SOURCE_FILES ${SAMPLE_SOURCES} ) -source_group( sample FILES ${SAMPLE_SOURCES} ) -include_directories( ${INCLUDE_DIRS} ) -add_library( sample SHARED ${SOURCE_FILES} ) -target_link_libraries( sample ${LIBRARIES} ) -set_target_properties( sample PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) -set_target_properties( sample PROPERTIES PREFIX "" ) -if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_sample DESCRIPTION "sample plugin" DISPLAY_NAME "sample" GROUP Runtime ) - install( TARGETS sample - DESTINATION "plugins" - COMPONENT Runtime_sample ) -endif( INSTALL_COMPONENT_RUNTIME ) -set( TARGET_LIST ${TARGET_LIST} sample CACHE INTERNAL "" ) -message( STATUS "Creating target sample - done" ) -endif( BUILD_PLUGIN_sample ) - - -# -# sig -# -option( BUILD_PLUGIN_sig "build sig plugin" OFF ) -if( BUILD_PLUGIN_sig ) -message( STATUS "Creating target sig" ) -set( SIG_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/sig.c" - ) -set( LIBRARIES ${GLOBAL_LIBRARIES} ) -set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) -set( DEFINITIONS "${GLOBAL_DEFINITIONS} -DNO_MEMMGR" ) -set( SOURCE_FILES ${SIG_SOURCES} ) -source_group( sig FILES ${SIG_SOURCES} ) -include_directories( ${INCLUDE_DIRS} ) -add_library( sig SHARED ${SOURCE_FILES} ) -target_link_libraries( sig ${LIBRARIES} ) -set_target_properties( sig PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) -set_target_properties( sig PROPERTIES PREFIX "" ) -if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_sig DESCRIPTION "sig plugin" DISPLAY_NAME "sig" GROUP Runtime ) - install( TARGETS sig - DESTINATION "plugins" - COMPONENT Runtime_sig ) -endif( INSTALL_COMPONENT_RUNTIME ) -set( TARGET_LIST ${TARGET_LIST} sig CACHE INTERNAL "" ) -message( STATUS "Creating target sig - done" ) -endif( BUILD_PLUGIN_sig ) diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in deleted file mode 100644 index 1b92ea3fa..000000000 --- a/src/plugins/Makefile.in +++ /dev/null @@ -1,54 +0,0 @@ - -COMMON_OBJ = ../common/obj_all/showmsg.o ../common/obj_all/utils.o ../common/obj_all/strlib.o \ - ../common/obj_all/minimalloc.o -COMMON_H = ../common/plugin.h ../common/cbasetypes.h \ - ../common/showmsg.h ../common/utils.h ../common/strlib.h \ - ../common/malloc.h - -PLUGINS = sample sig pid console - -@SET_MAKE@ - -##################################################################### -.PHONY : all $(PLUGINS) clean help - -all: $(PLUGINS) - -sample: sample@DLLEXT@ - -sig: sig@DLLEXT@ - -pid: pid@DLLEXT@ - -console: console@DLLEXT@ - -clean: - @echo " CLEAN plugins" - @rm -rf *.o - -help: - @echo "possible targets are $(PLUGINS:%='%') 'all' 'clean' 'help'" - @echo "'sample' - sample plugin" - @echo "'sig' - signal handler plugin" - @echo "'pid' - process id plugin" - @echo "'console' - console plugin" - @echo "'all' - builds all above targets" - @echo "'clean' - cleans builds and objects" - @echo "'help' - outputs this message" - -##################################################################### - -%@DLLEXT@: %.c - @echo " CC $<" - @@CC@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ -shared -o ../../plugins/$@ $< - -sig@DLLEXT@: sig.c $(COMMON_OBJ) - @echo " CC $<" - @@CC@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ -shared -o ../../plugins/$@ $< $(COMMON_OBJ) - -# missing common object files -../common/obj_all/%.o: ../common/%.c $(COMMON_H) - @$(MAKE) -C ../common txt - -../common/obj_all/mini%.o: ../common/%.c $(COMMON_H) - @$(MAKE) -C ../common txt diff --git a/src/plugins/console.c b/src/plugins/console.c deleted file mode 100644 index fc883a9f3..000000000 --- a/src/plugins/console.c +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#include "../common/plugin.h" - -#ifdef WIN32 - #define WIN32_LEAN_AND_MEAN - #include <windows.h> -#else - #define __USE_XOPEN - #include <sys/types.h> - #include <unistd.h> - #include <poll.h> - #include <string.h> -#endif -#include <stdio.h> // stdin, fgets - -#define INPUT_BUFSIZE 4096 -#define INPUT_INVALID 0 -#define INPUT_READY 1 -#define INPUT_WAITING 2 -#define INPUT_READING 3 -#define INPUT_CLOSED 4 - -////////////////////////////// -#ifdef WIN32 -////////////////////////////// - -// In windows the worker is a thread so it can access the same variables. -#define WORKER_FUNC_DECLARE(name) DWORD WINAPI worker_ ## name(LPVOID lpParameter) -#define WORKER_FUNC_START(name) DWORD WINAPI worker_ ## name(LPVOID lpParameter) { (void)lpParameter; { -#define WORKER_FUNC_END(name) } ExitThread(0); return 0; } -#define WORKER_EXECUTE(name,errvar) \ - do{ \ - DWORD dwThreadId; \ - buf.worker = CreateThread(NULL, 0, worker_ ## name, NULL, CREATE_SUSPENDED, &dwThreadId); \ - *(errvar) = ( buf.worker == NULL ); \ - }while(0) - -/// Buffer for asynchronous input -typedef struct _buffer { - char arr[INPUT_BUFSIZE]; - size_t len; - HANDLE worker; - HANDLE state_mux; // mutex for the state - char state; -} BUFFER; - -////////////////////////////// -#else -////////////////////////////// - -/// In linux the worker is a process so it needs to comunicate through pipes. -#define WORKER_FUNC_DECLARE(name) void worker_ ## name(void) -#define WORKER_FUNC_START(name) void worker_ ## name(void) { -#define WORKER_FUNC_END(name) _exit(0); } -#define WORKER_EXECUTE(name,errvar) \ - do{ \ - int pid = fork(); \ - if( pid == 0 ){ \ - worker_ ## name(); \ - } \ - *(errvar) = (pid == -1); \ - }while(0) - -#define PIPE_READ 0 -#define PIPE_WRITE 1 - -/// Buffer for asynchronous input -typedef struct _buffer { - char arr[INPUT_BUFSIZE]; - size_t len; - int data_pipe[2]; // pipe to receive data - int state_pipe[2]; // pipe to send state - char state; - unsigned close_unused_flag : 1; -} BUFFER; - -////////////////////////////// -#endif -////////////////////////////// - - - - - -////// Plugin information //////// - - - - - -PLUGIN_INFO = { - "Console", // Name - PLUGIN_ALL, // Target servers - "0.1", // Version - "1.03", // Minimum plugin engine version to run - "Console parser" // Short description -}; - -////// Plugin event list ////////// -// Format: <plugin function>,<event name> -// All registered functions to a event gets executed -// (In descending order) when its called. -// Multiple functions can be called by multiple events too, -// So it's up to your creativity ^^ -// -PLUGIN_EVENTS_TABLE = { - { "console_init", EVENT_PLUGIN_INIT }, - { "console_final", EVENT_PLUGIN_FINAL }, - { "console_autostart", EVENT_ATHENA_INIT }, - //{ "console_start", EVENT_CONSOLE_START },//## add these events to the plugins framework - //{ "console_stop", EVENT_CONSOLE_STOP }, - { "console_stop", EVENT_ATHENA_FINAL }, - { NULL, NULL } -}; - - - - - -///// Variables ///// - - - - - -// Imported functions -typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data); -int (*add_timer_func_list)(TimerFunc func, char* name); -int (*add_timer_interval)(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval); -int (*delete_timer)(int tid, TimerFunc func); -unsigned int (*gettick)(void); -int (*parse_console)(const char* buf); - -// Locals -int tid = -1; // timer id -BUFFER buf; // input buffer -WORKER_FUNC_DECLARE(getinput); // worker for the input buffer - - - - - -//////// Asynchronous input functions ////////// - - - - - -////////////////////////////// -#ifdef WIN32 -////////////////////////////// -// -// --=== Asynchronous console input ===-- -// -// On windows a thread is used (both threads have access to the same data). -// The worker threads starts suspended and is resumed when data is required. -// After getting the data, the worker thread updates the state variable and -// suspends itself. -// -// A mutex is used to synchronize access to the state variable between the -// threads. Access and updates to state are probably already atomic so the -// mutex shouldn't be needed, but using it is more correct so it stays. -// -// Note: The Worker thread only starts to get input data when further data is -// requested. This is a design choise and brings no real advantage or -// disadvantage I can think of. -// - -/// Returns the state of the input -char input_getstate() -{ - char state; - - WaitForSingleObject(buf.state_mux, INFINITE); - state = buf.state; - ReleaseMutex(buf.state_mux); - - return state; -} - -/// Sets the state of the input -void input_setstate(char state) -{ - char oldstate; - - // update state - WaitForSingleObject(buf.state_mux, INFINITE); - oldstate = buf.state; - buf.state = state; - ReleaseMutex(buf.state_mux); - - if( state == INPUT_READY && oldstate == INPUT_READING ) - {// data has become available - SuspendThread(buf.worker); - } else if( state == INPUT_WAITING ) - {// input is waiting for data - ResumeThread(buf.worker); - //} else if( state == INPUT_READING ) - //{// worker is reading data - } else if( state == INPUT_CLOSED ) - {// end the input - CloseHandle(buf.state_mux); - TerminateThread(buf.worker, 0); - } -} - -/// Gets the next state of the input -#define input_nextstate() input_getstate() - -/// Returns if data is available from asynchronous input. -/// Requests data if none is available. -int input_hasdata(void) -{ - if( input_getstate() == INPUT_READY ) - {// buffer is ready - if( buf.len > 0 ) - return 1; // data found ;) - // request data from the worker - input_setstate(INPUT_WAITING); - } - return 0; // no data -} - -/// Initialize asynchronous input -int input_init(void) -{ - int err = 0; - - memset(&buf, 0, sizeof(buf)); - buf.state_mux = CreateMutex(NULL, FALSE, NULL); - if( buf.state_mux == NULL ) - {// failed to create state mutex - return 1; - } - buf.len = 0; - input_setstate(INPUT_READY); - WORKER_EXECUTE(getinput, &err); - if( err ) - {// failed to start worker - input_setstate(INPUT_CLOSED); - } - - return err; -} - -/// Finalize asynchronous input -int input_final(void) -{ - input_setstate(INPUT_CLOSED); - return 0; -} - -////////////////////////////// -#else -////////////////////////////// -// -// --=== Asynchronous console input ===-- -// -// On the other systems a process is used and pipes are used to comunicate. -// The worker process receives status updates through one of the pipes either -// requesting data or ending the worker. -// The other pipe is used by the worker to send the input data and is checked -// for data by the main thread in the timer function. -// -// Note: The Worker thread only starts to get input data when further data is -// requested. This is a design choise and brings no real advantage or -// disadvantage I can think of. -// - -/// Returns the state of the input -#define input_getstate() buf.state - -/// Sets the state of the input -void input_setstate(char state) { - size_t fileReadCount = 0; - if( state == INPUT_READY && input_getstate() == INPUT_READING ) {// send data from the worker to the main process - fileReadCount = write(buf.data_pipe[PIPE_WRITE], &buf.len, sizeof(buf.len)); - fileReadCount = write(buf.data_pipe[PIPE_WRITE], &buf.arr, buf.len); - } else if( state == INPUT_WAITING ) { - if( buf.close_unused_flag == 0 ) {// close unused pipe sides in the main process - close(buf.data_pipe[PIPE_WRITE]); - close(buf.state_pipe[PIPE_READ]); - buf.close_unused_flag = 1; - } - // send the next state - fileReadCount = write(buf.state_pipe[PIPE_WRITE], &state, sizeof(state)); - } else if( state == INPUT_READING ) { - if( buf.close_unused_flag == 0 ) {// close unused pipe sides in the worker process - close(buf.data_pipe[PIPE_READ]); - close(buf.state_pipe[PIPE_WRITE]); - buf.close_unused_flag = 1; - } - } else if( state == INPUT_CLOSED ) {// send next state to the worker and close the pipes - fileReadCount = write(buf.state_pipe[PIPE_WRITE], &state, sizeof(state)); - close(buf.data_pipe[PIPE_WRITE]); - close(buf.data_pipe[PIPE_READ]); - close(buf.state_pipe[PIPE_WRITE]); - close(buf.state_pipe[PIPE_READ]); - } - buf.state = state; -} - -/// Waits for the next state of the input -char input_nextstate() -{ - char state = INPUT_CLOSED; - int bytes = 0; - - while( bytes == 0 ) - bytes = read(buf.state_pipe[PIPE_READ], &state, sizeof(state)); - if( bytes == -1 ) - {// error, terminate worker - input_setstate(INPUT_CLOSED); - } - return state; -} - -/// Returns if data is available from asynchronous input. -/// If data is available, it's put in the local buffer. -int input_hasdata() -{ - struct pollfd fds; - int hasData; - size_t fileReadCount; - - - if( input_getstate() == INPUT_READY ) {// start getting data - input_setstate(INPUT_WAITING); - return 0; - } - // check if data is available - fds.fd = buf.data_pipe[PIPE_READ]; - fds.events = POLLRDNORM; - hasData = ( poll(&fds,1,0) > 0 ); - if( hasData ) {// read the data from the pipe - fileReadCount = read(buf.data_pipe[PIPE_READ], &buf.len, sizeof(buf.len)); - fileReadCount = read(buf.data_pipe[PIPE_READ], buf.arr, buf.len); - input_setstate(INPUT_READY); - } - - return hasData; -} - -/// Initialize asynchronous input -int input_init(void) -{ - int err = 0; - - memset(&buf, 0, sizeof(buf)); - if( pipe(buf.data_pipe) ) - {// error creating data pipe - return 1; - } - if( pipe(buf.state_pipe) ) - {// error creating state pipe - close(buf.data_pipe[PIPE_READ]); - close(buf.data_pipe[PIPE_WRITE]); - return 1; - } - buf.len = 0; - input_setstate(INPUT_READY); - WORKER_EXECUTE(getinput, &err); - if( err ){ - //printf("input_init failed to start worker (%d)\n", err); - input_setstate(INPUT_CLOSED); - } - - return err; -} - -/// Finalize asynchronous input -int input_final(void) -{ - close(buf.data_pipe[PIPE_READ]); - close(buf.data_pipe[PIPE_WRITE]); - close(buf.state_pipe[PIPE_READ]); - close(buf.state_pipe[PIPE_WRITE]); - return 0; -} - -////////////////////////////// -#endif -////////////////////////////// - - - -/// Returns the input data array -#define input_getdata() buf.arr - -/// Returns the input data length -#define input_getlen() buf.len - -/// Clear the input data -#define input_clear() ( buf.len = 0 ) - -/// Worker thread/process that gets input -WORKER_FUNC_START(getinput) - while( input_nextstate() != INPUT_CLOSED ) - {// get input - input_setstate(INPUT_READING); - buf.arr[0] = '\0'; - if( fgets(buf.arr, INPUT_BUFSIZE, stdin) != NULL ) - buf.len = strlen(buf.arr); - input_setstate(INPUT_READY); - } -WORKER_FUNC_END(getinput) - - - - - -//////// Plugin console functions ////////// - - - - - -/// Timer function that checks if there's assynchronous input data and feeds parse_console() -/// The input reads one line at a time and line terminators are removed. -int console_getinputtimer(int tid, unsigned int tick, int id, intptr_t data) -{ - char* cmd; - size_t len; - - if( input_hasdata() ){ - - // get data (removes line terminators) - cmd = input_getdata(); - len = input_getlen(); - while( len > 0 && (cmd[len-1] == '\r' || cmd[len-1] == '\n') ) - cmd[--len] = '\0'; - - // parse data - parse_console(cmd); - input_clear(); - } - - return 0; -} - -/// Start the console -void console_start(void) -{ - if( input_init() ){ - return; - } - //##TODO add a 'startupcmd' config options - //parse_console("help"); - add_timer_func_list(console_getinputtimer,"console_getinputtimer"); - tid = add_timer_interval(gettick(),console_getinputtimer,0,0,250);//##TODO add a 'timerperiod' config option -} - -void console_autostart(void) -{//##TODO add an 'autostart' config option - console_start(); -} - -/// Stop the console -void console_stop(void) -{ - if( tid != -1 ){ - delete_timer(tid, console_getinputtimer); - input_final(); - } - return; -} - -/// Test the console for compatibility -int console_test(void) -{// always compatible at the moment, maybe test if standard input is available? - return 1; -} - - -/// Initialize the console -void console_init(void) -{ - // import symbols - IMPORT_SYMBOL(add_timer_interval, SYMBOL_ADD_TIMER_INTERVAL); - IMPORT_SYMBOL(add_timer_func_list, SYMBOL_ADD_TIMER_FUNC_LIST); - IMPORT_SYMBOL(delete_timer, SYMBOL_DELETE_TIMER); - IMPORT_SYMBOL(gettick, SYMBOL_GETTICK); - IMPORT_SYMBOL(parse_console, SYMBOL_PARSE_CONSOLE); - //printf("%d -> add_timer_func_list=0x%x\n", SYMBOL_ADD_TIMER_FUNC_LIST, (int)add_timer_func_list); - //printf("%d -> add_timer_interval=0x%x\n", SYMBOL_ADD_TIMER_INTERVAL, (int)add_timer_interval); - //printf("%d -> delete_timer=0x%x\n", SYMBOL_DELETE_TIMER, (int)delete_timer); - //printf("%d -> gettick=0x%x\n", SYMBOL_GETTICK, (int)gettick); - //printf("%d -> parse_console=0x%x\n", SYMBOL_PARSE_CONSOLE, (int)parse_console); -} - -/// Finalize the console -void console_final(void) -{ -} diff --git a/src/plugins/console.def b/src/plugins/console.def deleted file mode 100644 index df4bd1d46..000000000 --- a/src/plugins/console.def +++ /dev/null @@ -1,13 +0,0 @@ -EXPORTS - ; common exports - plugin_info DATA - plugin_event_table DATA - plugin_call_table DATA - - ; console-specific exports - console_init - console_final - console_test - console_autostart - console_start - console_stop diff --git a/src/plugins/dbghelpplug.c b/src/plugins/dbghelpplug.c deleted file mode 100644 index 85556503b..000000000 --- a/src/plugins/dbghelpplug.c +++ /dev/null @@ -1,1896 +0,0 @@ -/* - * 2008 January 19 - * - * The author disclaims copyright to this source code. In place of - * a legal notice, here is a blessing: - * - * May you do good and not evil. - * May you find forgiveness for yourself and forgive others. - * May you share freely, never taking more than you give. - * - ******************************************************************** - * - * DONE: - * - Command line - * - Windows version - * - Exception - * - Registers - * - Stacktrace (frame number starting at 0) - * + Functions: - * - address - * - name - * - offset in the function - * - line number and source file - * - source code of the line (external source) - * - function parameters - * - local function variables - * + Variables/parameters: - * - variable name - * - variable type (char/wchar, integers, floats, enums, arrays, - * pointers, structs, unions, ...) - * - readability of memory - * - value of char/wchar - * - value of integers - * - value of floats - * - value of enums (hex number) - * - values of arrays - * - address of pointers - * - value of simple pointers (not pointing to another pointer) - * - show (char*) and (wchar*) as nul-terminated strings - * - show chars/wchar escaped - * + Modules: - * - base address - * - file - * - version - * - size - * - * TODO: - * + Variables/parameters: - * - structure members - * - union members - * - globals - * - Portability to MinGW - * - * $Id$ - */ - -#ifdef _WIN32 - - -///////////////////////////////////////////////////////////////////// -// Include files -// - -#include <assert.h> - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - -#define _NO_CVCONST_H -#include <dbghelp.h> - -#include <stdio.h> -#include <stdlib.h> -#include <time.h> - - -///////////////////////////////////////////////////////////////////// -// Types from Cvconst.h (DIA SDK) -// - -#ifdef _NO_CVCONST_H - -typedef enum _BasicType -{ - btNoType = 0, - btVoid = 1, - btChar = 2, - btWChar = 3, - btInt = 6, - btUInt = 7, - btFloat = 8, - btBCD = 9, - btBool = 10, - btLong = 13, - btULong = 14, - btCurrency = 25, - btDate = 26, - btVariant = 27, - btComplex = 28, - btBit = 29, - btBSTR = 30, - btHresult = 31 -} BasicType; - -typedef enum _UdtKind -{ - UdtStruct, - UdtClass, - UdtUnion -} UdtKind; -/* -typedef enum _SymTag { - SymTagNull = 0, - SymTagExe = 1, - SymTagCompiland = 2, - SymTagCompilandDetails = 3, - SymTagCompilandEnv = 4, - SymTagFunction = 5, - SymTagBlock = 6, - SymTagData = 7, - SymTagAnnotation = 8, - SymTagLabel = 9, - SymTagPublicSymbol = 10, - SymTagUDT = 11, - SymTagEnum = 12, - SymTagFunctionType = 13, - SymTagPointerType = 14, - SymTagArrayType = 15, - SymTagBaseType = 16, - SymTagTypedef = 17, - SymTagBaseClass = 18, - SymTagFriend = 19, - SymTagFunctionArgType = 20, - SymTagFuncDebugStart = 21, - SymTagFuncDebugEnd = 22, - SymTagUsingNamespace = 23, - SymTagVTableShape = 24, - SymTagVTable = 25, - SymTagCustom = 26, - SymTagThunk = 27, - SymTagCustomType = 28, - SymTagManagedType = 29, - SymTagDimension = 30 -} SymTag; -*/ -#endif /* _NO_CVCONST_H */ - - -///////////////////////////////////////////////////////////////////// -// dbghelp function prototypes -// - -typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)( - HANDLE hProcess, - DWORD ProcessId, - HANDLE hFile, - MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam -); -typedef BOOL (WINAPI *SYMINITIALIZE)( - HANDLE hProcess, - PSTR UserSearchPath, - BOOL fInvadeProcess -); -typedef DWORD (WINAPI *SYMSETOPTIONS)( - DWORD SymOptions -); -typedef DWORD (WINAPI *SYMGETOPTIONS)( - VOID -); -typedef BOOL (WINAPI *SYMCLEANUP)( - HANDLE hProcess -); -typedef BOOL (WINAPI *SYMGETTYPEINFO)( - HANDLE hProcess, - DWORD64 ModBase, - ULONG TypeId, - IMAGEHLP_SYMBOL_TYPE_INFO GetType, - PVOID pInfo -); -typedef BOOL (WINAPI *SYMGETLINEFROMADDR)( - HANDLE hProcess, - DWORD dwAddr, - PDWORD pdwDisplacement, - PIMAGEHLP_LINE Line -); -typedef BOOL (WINAPI *SYMENUMSYMBOLS)( - HANDLE hProcess, - ULONG64 BaseOfDll, - PCSTR Mask, - PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, - PVOID UserContext -); -typedef BOOL (WINAPI *SYMSETCONTEXT)( - HANDLE hProcess, - PIMAGEHLP_STACK_FRAME StackFrame, - PIMAGEHLP_CONTEXT Context -); -typedef BOOL (WINAPI *SYMFROMADDR)( - HANDLE hProcess, - DWORD64 Address, - PDWORD64 Displacement, - PSYMBOL_INFO Symbol -); -typedef BOOL (WINAPI *STACKWALK)( - DWORD MachineType, - HANDLE hProcess, - HANDLE hThread, - LPSTACKFRAME StackFrame, - PVOID ContextRecord, - PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, - PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, - PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, - PTRANSLATE_ADDRESS_ROUTINE TranslateAddress -); -typedef PVOID (WINAPI *SYMFUNCTIONTABLEACCESS)( - HANDLE hProcess, - DWORD AddrBase -); -typedef DWORD (WINAPI *SYMGETMODULEBASE)( - HANDLE hProcess, - DWORD dwAddr -); - - -///////////////////////////////////////////////////////////////////// -// Custom info - -/// Internal structure used to pass some data around -typedef struct _InternalData { - // PrintStacktrace - FILE* log_file; - STACKFRAME* pStackframe; - HANDLE hProcess; - DWORD nr_of_frame; - - // PrintFunctionDetail - BOOL as_arg_list; - BOOL log_params; - BOOL log_locals; - BOOL log_globals; - DWORD nr_of_var; - - // PrintDataInfo - ULONG64 modBase; -} InterData; - -/// dbghelp dll filename -#define DBGHELP_DLL "dbghelp.dll" - -// Default report filename, used when the module path is unavailable -#define DBG_DEFAULT_FILENAME "athena" - -// Extended information printed in the console -#define DBG_EXTENDED_INFORMATION \ - "Please report the crash in the bug tracker:\n" \ - "http://www.eathena.ws/board/index.php?autocom=bugtracker\n" - - -///////////////////////////////////////////////////////////////////// -// Global variables - -HANDLE dbghelp_dll = INVALID_HANDLE_VALUE; -MINIDUMPWRITEDUMP MiniDumpWriteDump_ = NULL; -SYMINITIALIZE SymInitialize_ = NULL; -SYMSETOPTIONS SymSetOptions_ = NULL; -SYMGETOPTIONS SymGetOptions_ = NULL; -SYMCLEANUP SymCleanup_ = NULL; -SYMGETTYPEINFO SymGetTypeInfo_ = NULL; -SYMGETLINEFROMADDR SymGetLineFromAddr_ = NULL; -SYMENUMSYMBOLS SymEnumSymbols_ = NULL; -SYMSETCONTEXT SymSetContext_ = NULL; -SYMFROMADDR SymFromAddr_ = NULL; -STACKWALK StackWalk_ = NULL; -SYMFUNCTIONTABLEACCESS SymFunctionTableAccess_ = NULL; -SYMGETMODULEBASE SymGetModuleBase_ = NULL; - - - -///////////////////////////////////////////////////////////////////// -// Code - - -/// Writes the minidump to file. The callback function will at the -/// same time write the list of modules to the log file. -/// -/// @param file Filename of the minidump -/// @param ptrs Exception info -/// @param module_callback Callback for MiniDumpWriteDump -/// @param log_file Log file -static VOID -Dhp__WriteMinidumpFile( - const char* file, - PEXCEPTION_POINTERS ptrs, - MINIDUMP_CALLBACK_ROUTINE module_callback, - FILE* log_file) -{ - // open minidump file - HANDLE minidump_file = CreateFileA( - file, - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - if( minidump_file != INVALID_HANDLE_VALUE ) - { - MINIDUMP_EXCEPTION_INFORMATION expt_info; - MINIDUMP_CALLBACK_INFORMATION dump_cb_info; - - expt_info.ThreadId = GetCurrentThreadId(); - expt_info.ExceptionPointers = ptrs; - expt_info.ClientPointers = FALSE; - - dump_cb_info.CallbackRoutine = module_callback; - dump_cb_info.CallbackParam = (void*)log_file; - - if( module_callback != NULL && log_file != NULL ) - fprintf(log_file, "\n\nLoaded modules:\n"); - - MiniDumpWriteDump_( - GetCurrentProcess(), - GetCurrentProcessId(), - minidump_file, - MiniDumpNormal, - ptrs ? &expt_info : NULL, - NULL, - &dump_cb_info - ); - - CloseHandle(minidump_file); - } -} - - -/// Prints module information to the log file. -/// Used as a callback to MiniDumpWriteDump. -/// -/// @param data Log file -/// @param callback_input -/// @param callback_output -/// @return -static BOOL CALLBACK -Dhp__PrintModuleInfoCallback( - void* data, - CONST PMINIDUMP_CALLBACK_INPUT callback_input, - PMINIDUMP_CALLBACK_OUTPUT callback_output) -{ - if( data != NULL && - callback_input != NULL && - callback_input->CallbackType == ModuleCallback) - { - FILE* log_file = (FILE*)data; - MINIDUMP_MODULE_CALLBACK module = callback_input->Module; - - fprintf(log_file, "0x%p", module.BaseOfImage); - - fprintf(log_file, " %ws", module.FullPath, log_file); - - fprintf(log_file, " (%d.%d.%d.%d, %d bytes)\n", - HIWORD(module.VersionInfo.dwFileVersionMS), - LOWORD(module.VersionInfo.dwFileVersionMS), - HIWORD(module.VersionInfo.dwFileVersionLS), - LOWORD(module.VersionInfo.dwFileVersionLS), - module.SizeOfImage); - } - - return TRUE; -} - - -/// Prints details about the current process, platform and exception -/// information to the log file. -/// -/// @param exception Exception info -/// @param context Exception context -/// @param log_file Log file -static VOID -Dhp__PrintProcessInfo( - EXCEPTION_RECORD* exception, - CONTEXT* context, - FILE* log_file) -{ - OSVERSIONINFOA oi; - LPSTR cmd_line; - - fprintf(log_file, - "\nProcess info:\n"); - - // print the command line - cmd_line = GetCommandLineA(); - if( cmd_line ) - fprintf(log_file, - "Cmd line: %s\n", - cmd_line); - - // print information about the OS - oi.dwOSVersionInfoSize = sizeof(oi); - GetVersionExA(&oi); - fprintf(log_file, - "Platform: Windows OS version %d.%d build %d %s\n", - oi.dwMajorVersion, oi.dwMinorVersion, oi.dwBuildNumber, oi.szCSDVersion); - - // print the exception code - if( exception ) - { - fprintf(log_file, - "\nException:\n" - "0x%x", - exception->ExceptionCode); - switch( exception->ExceptionCode ) - { -#define PRINT(x) case x: fprintf(log_file, " "#x); break - PRINT(EXCEPTION_ACCESS_VIOLATION); - PRINT(EXCEPTION_DATATYPE_MISALIGNMENT); - PRINT(EXCEPTION_BREAKPOINT); - PRINT(EXCEPTION_SINGLE_STEP); - PRINT(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - PRINT(EXCEPTION_FLT_DENORMAL_OPERAND); - PRINT(EXCEPTION_FLT_DIVIDE_BY_ZERO); - PRINT(EXCEPTION_FLT_INEXACT_RESULT); - PRINT(EXCEPTION_FLT_INVALID_OPERATION); - PRINT(EXCEPTION_FLT_OVERFLOW); - PRINT(EXCEPTION_FLT_STACK_CHECK); - PRINT(EXCEPTION_FLT_UNDERFLOW); - PRINT(EXCEPTION_INT_DIVIDE_BY_ZERO); - PRINT(EXCEPTION_INT_OVERFLOW); - PRINT(EXCEPTION_PRIV_INSTRUCTION); - PRINT(EXCEPTION_IN_PAGE_ERROR); - PRINT(EXCEPTION_ILLEGAL_INSTRUCTION); - PRINT(EXCEPTION_NONCONTINUABLE_EXCEPTION); - PRINT(EXCEPTION_STACK_OVERFLOW); - PRINT(EXCEPTION_INVALID_DISPOSITION); - PRINT(EXCEPTION_GUARD_PAGE); - PRINT(EXCEPTION_INVALID_HANDLE); -#undef PRINT - } - - // print where the fault occured - fprintf(log_file, " at location 0x%p", exception->ExceptionAddress); - - // if the exception was an access violation, print additional information - if( exception->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && exception->NumberParameters >= 2 ) - fprintf(log_file, " %s location 0x%p", exception->ExceptionInformation[0] ? "writing to" : "reading from", exception->ExceptionInformation[1]); - - fprintf(log_file, "\n"); - } - - // print the register info - if( context ) - { -#if defined(_M_IX86) - fprintf(log_file, - "\nRegisters:\n"); - if( context->ContextFlags & CONTEXT_INTEGER ) - { - fprintf(log_file, - "eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n", - context->Eax, context->Ebx, context->Ecx, - context->Edx, context->Esi, context->Edi); - } - if( context->ContextFlags & CONTEXT_CONTROL ) - { - fprintf(log_file, - "eip=%08x esp=%08x ebp=%08x iopl=%1x %s %s %s %s %s %s %s %s %s %s\n", - context->Eip, context->Esp, context->Ebp, - (context->EFlags >> 12) & 3, // IOPL level value - context->EFlags & 0x00100000 ? "vip" : " ", // VIP (virtual interrupt pending) - context->EFlags & 0x00080000 ? "vif" : " ", // VIF (virtual interrupt flag) - context->EFlags & 0x00000800 ? "ov" : "nv", // VIF (virtual interrupt flag) - context->EFlags & 0x00000400 ? "dn" : "up", // OF (overflow flag) - context->EFlags & 0x00000200 ? "ei" : "di", // IF (interrupt enable flag) - context->EFlags & 0x00000080 ? "ng" : "pl", // SF (sign flag) - context->EFlags & 0x00000040 ? "zr" : "nz", // ZF (zero flag) - context->EFlags & 0x00000010 ? "ac" : "na", // AF (aux carry flag) - context->EFlags & 0x00000004 ? "po" : "pe", // PF (parity flag) - context->EFlags & 0x00000001 ? "cy" : "nc"); // CF (carry flag) - } - if( context->ContextFlags & CONTEXT_SEGMENTS ) - { - fprintf(log_file, - "cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x", - context->SegCs, - context->SegSs, - context->SegDs, - context->SegEs, - context->SegFs, - context->SegGs, - context->EFlags); - if( context->ContextFlags & CONTEXT_CONTROL ) - fprintf(log_file, - " efl=%08x", - context->EFlags); - fprintf(log_file, "\n"); - } - else if( context->ContextFlags & CONTEXT_CONTROL ) - fprintf(log_file, - " efl=%08x\n", - context->EFlags); -#else /* defined(_M_IX86) */ - //TODO add more processors -#endif - } -} - - -/// Prints the typename of the symbol. -/// -/// @param typeIndex Type index of the symbol -/// @param symtag Symbol tag -/// @param withParens If brackets are printed around the typename -/// @param interData Inter data -static VOID -Dhp__PrintTypeName( - DWORD typeIndex, - DWORD symtag, - BOOL withParens, - InterData* interData) -{ - // inter data - FILE* log_file; - HANDLE hProcess; - ULONG64 modBase; - // - assert( interData != NULL ); - log_file = interData->log_file; - hProcess = interData->hProcess; - modBase = interData->modBase; - - if( withParens ) - fprintf(log_file, "("); - - switch( symtag ) - { - case SymTagEnum: - { - WCHAR* pwszTypeName; - - if( SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_SYMNAME, &pwszTypeName) ) - { - fprintf(log_file, "enum %ls", pwszTypeName); - LocalFree(pwszTypeName); - } - else - fprintf(log_file, "enum <symname not found>"); - } - break; - case SymTagBaseType: - { - DWORD basetype; - ULONG64 length = 0; - - SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_LENGTH, &length); - if( !SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_BASETYPE, &basetype) ) - { - fprintf(log_file, "<basetype not found>"); - break; - } - switch( basetype ) - { - case btVoid: fprintf(log_file, "void"); break; - case btChar: fprintf(log_file, "char"); break; - case btWChar: fprintf(log_file, "wchar"); break; - case btULong: fprintf(log_file, "unsigned "); // next - case btLong: fprintf(log_file, "long"); break; - case btUInt: fprintf(log_file, "unsigned "); // next - case btInt: - if( length == sizeof(char) ) fprintf(log_file, "char"); - else if( length == sizeof(short) ) fprintf(log_file, "short"); - else if( length == sizeof(int) ) fprintf(log_file, "int"); - else if( length == sizeof(long long) ) fprintf(log_file, "long long"); - else fprintf(log_file, "<int%d>", length*8); - break; - case btFloat: - if( length == sizeof(float) ) fprintf(log_file, "float"); - else if( length == sizeof(double) ) fprintf(log_file, "double"); - else if( length == sizeof(long double) ) fprintf(log_file, "long double"); - else fprintf(log_file, "<float%d>", length*8); - break; - default: fprintf(log_file, "<TODO name of basetype %d %d>", basetype, length); break; - } - } - break; - case SymTagPointerType: - { - DWORD subtype; - DWORD subtag; - - if( !SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_TYPE, &subtype) ) - fprintf(log_file, "<type not found>*"); - else if( !SymGetTypeInfo_(hProcess, modBase, subtype, TI_GET_SYMTAG, &subtag) ) - fprintf(log_file, "<symtag not found>*"); - else - { - Dhp__PrintTypeName(subtype, subtag, FALSE, interData); - fprintf(log_file, "*"); - } - } - break; - case SymTagArrayType: - { - DWORD childTypeIndex; - DWORD childSymtag; - - // print root type - childTypeIndex = typeIndex; - childSymtag = symtag; - for( ; ; ) - { - if( !SymGetTypeInfo_( hProcess, modBase, childTypeIndex, TI_GET_TYPE, &childTypeIndex) ) - { - fprintf(log_file, "<child type not found>"); - break; - } - if( !SymGetTypeInfo_( hProcess, modBase, childTypeIndex, TI_GET_SYMTAG, &childSymtag) ) - { - fprintf(log_file, "<child symtag not found>"); - break; - } - if( childSymtag != SymTagArrayType ) - { - Dhp__PrintTypeName(childTypeIndex, childSymtag, FALSE, interData); - break; - } - // next dimension - } - // print dimensions - childTypeIndex = typeIndex; - childSymtag = symtag; - for( ; childSymtag == SymTagArrayType ; ) - { - DWORD childCount; - if( !SymGetTypeInfo_( hProcess, modBase, childTypeIndex, TI_GET_COUNT, &childCount) ) - fprintf(log_file, "[<count not found>]"); - else - fprintf(log_file, "[%u]", childCount); - if( !SymGetTypeInfo_( hProcess, modBase, childTypeIndex, TI_GET_TYPE, &childTypeIndex) ) - { - fprintf(log_file, "<child type not found>"); - break; - } - if( !SymGetTypeInfo_( hProcess, modBase, childTypeIndex, TI_GET_SYMTAG, &childSymtag) ) - { - fprintf(log_file, "<child symtag not found>"); - break; - } - // next dimension - } - } - break; - default: - { - WCHAR* pSymname; - DWORD udtkind; - - if( SymGetTypeInfo_( hProcess, modBase, typeIndex, TI_GET_UDTKIND, &udtkind) ) - { - switch( (UdtKind)udtkind ) - { - case UdtStruct: fprintf(log_file, "struct "); break; - case UdtClass: fprintf(log_file, "class "); break; - case UdtUnion: fprintf(log_file, "union "); break; - default: fprintf(log_file, "<unknown udtkind %d> ", udtkind); break; - } - } - if( SymGetTypeInfo_( hProcess, modBase, typeIndex, TI_GET_SYMNAME, &pSymname ) ) - { - fprintf(log_file, "%ls", pSymname); - LocalFree( pSymname ); - } - else - fprintf(log_file, "<TODO typename of symtag %d>", symtag); break; - } - break; - } - - if( withParens ) - fprintf(log_file, ")"); -} - - -/// Prints the bytes in the target location. -/// -/// @param log_file Log file -/// @param p Pointer to the data -/// @param length Length of the data in bytes -static VOID -Dhp__PrintValueBytes( - FILE* log_file, - BYTE* p, - ULONG64 length) -{ - ULONG64 i; - - fprintf(log_file, "<bytes:"); - for( i = 0; i < length; ++i ) - { - fprintf(log_file, "%02X", p[i]); - } - fprintf(log_file, ">"); -} - - -/// Prints a wide string/char value. -/// -/// @param log_file Log file -/// @param p Pointer to the value -/// @param length Length of the value in bytes -static VOID -Dhp__PrintValueWideChars( - FILE* log_file, - WCHAR* wstr, - ULONG64 length, - BOOL isString) -{ - ULONG64 i; - char* buf; - char delim; - - length /= sizeof(WCHAR); - delim = ( isString || length > 1 ? '\"' : '\'' ); - fprintf(log_file, "%c", delim); - buf = (char *)LocalAlloc(LMEM_FIXED, MB_CUR_MAX+1); - buf[MB_CUR_MAX] = '\0'; - for( i = 0; i < length; ++i ) - { - int n; - switch( wstr[i] ) - { - case L'\"': fprintf(log_file, "\\\""); break; - case L'\'': fprintf(log_file, "\\\'"); break; - case L'\\': fprintf(log_file, "\\\\"); break; - case L'\a': fprintf(log_file, "\\a"); break; - case L'\b': fprintf(log_file, "\\b"); break; - case L'\f': fprintf(log_file, "\\f"); break; - case L'\n': fprintf(log_file, "\\n"); break; - case L'\r': fprintf(log_file, "\\r"); break; - case L'\t': fprintf(log_file, "\\t"); break; - case L'\v': fprintf(log_file, "\\v"); break; - default: - if( iswprint(wstr[i]) && (n=wctomb(buf, wstr[i])) > 0 ) - { - buf[n] = '\0'; - fprintf(log_file, "%s", buf); - } - else fprintf(log_file, "\\u%04X", wstr[i]); - break; - } - } - LocalFree(buf); - fprintf(log_file, "%c", delim); -} - - -/// Prints a string/char value. -/// -/// @param log_file Log file -/// @param p Pointer to the value -/// @param length Length of the value in bytes -static VOID -Dhp__PrintValueChars( - FILE* log_file, - char* str, - ULONG64 length, - BOOL isString) -{ - ULONG64 i; - char delim; - - length /= sizeof(char); - delim = ( isString || length > 1 ? '\"' : '\'' ); - fprintf(log_file, "%c", delim); - for( i = 0; i < length; ++i ) - { - switch( str[i] ) - { - case '\"': fprintf(log_file, "\\\""); break; - case '\'': fprintf(log_file, "\\\'"); break; - case '\\': fprintf(log_file, "\\\\"); break; - case '\a': fprintf(log_file, "\\a"); break; - case '\b': fprintf(log_file, "\\b"); break; - case '\f': fprintf(log_file, "\\f"); break; - case '\n': fprintf(log_file, "\\n"); break; - case '\r': fprintf(log_file, "\\r"); break; - case '\t': fprintf(log_file, "\\t"); break; - case '\v': fprintf(log_file, "\\v"); break; - default: - if( isprint((unsigned char)str[i]) ) fprintf(log_file, "%c", str[i]); - else fprintf(log_file, "\\x%02X", (unsigned char)str[i]); - break; - } - } - fprintf(log_file, "%c", delim); -} - - -/// Prints a float value. -/// -/// @param log_file Log file -/// @param p Pointer to the value -/// @param length Length of the value in bytes -static VOID -Dhp__PrintValueFloat( - FILE* log_file, - VOID* p, - ULONG64 length) -{ - if( length == sizeof(float) ) fprintf(log_file, "%f", *(float*)p); - else if( length == sizeof(double) ) fprintf(log_file, "%lf", *(double*)p); - else if( length == sizeof(long double) ) fprintf(log_file, "%Lf", *(long double*)p); - else - { - fprintf(log_file, "<unexpected length %I64u>", length); - Dhp__PrintValueBytes(log_file, (BYTE*)p, length); - } -} - - -/// Prints a hex value. -/// -/// @param log_file Log file -/// @param p Pointer to the value -/// @param length Length of the value in bytes -static VOID -Dhp__PrintValueHex( - FILE* log_file, - VOID* p, - ULONG64 length) -{ - if( length == sizeof(UINT32) ) fprintf(log_file, "0x%I32X", *(UINT32*)p); - else if( length == sizeof(UINT64) ) fprintf(log_file, "0x%I64X", *(UINT64*)p); - else if( length == sizeof(char) ) fprintf(log_file, "0x%X", *(unsigned char*)p); - else if( length == sizeof(short) ) fprintf(log_file, "0x%X", *(unsigned short*)p); - else if( length == sizeof(int) ) fprintf(log_file, "0x%x", *(unsigned int*)p); - else if( length == sizeof(long) ) fprintf(log_file, "0x%lX", *(unsigned long*)p); - else if( length == sizeof(long long) ) fprintf(log_file, "0x%llX", *(unsigned long long*)p); - else - { - fprintf(log_file, "<unexpected length %I64u>", length); - Dhp__PrintValueBytes(log_file, (BYTE*)p, length); - } -} - - -/// Prints an unsigned integer value. -/// -/// @param log_file Log file -/// @param p Pointer to the value -/// @param length Length of the value in bytes -static VOID -Dhp__PrintValueUnsigned( - FILE* log_file, - VOID* p, - ULONG64 length) -{ - if( length == sizeof(INT32) ) fprintf(log_file, "%I32u", *(INT32*)p); - else if( length == sizeof(INT64) ) fprintf(log_file, "%I64u", *(INT64*)p); - else if( length == sizeof(char) ) fprintf(log_file, "%u", *(unsigned char*)p); - else if( length == sizeof(short) ) fprintf(log_file, "%u", *(unsigned short*)p); - else if( length == sizeof(int) ) fprintf(log_file, "%u", *(unsigned int*)p); - else if( length == sizeof(long) ) fprintf(log_file, "%lu", *(unsigned long*)p); - else if( length == sizeof(long long) ) fprintf(log_file, "%llu", *(unsigned long long*)p); - else - { - fprintf(log_file, "<unexpected length %I64u>", length); - Dhp__PrintValueBytes(log_file, (BYTE*)p, length); - } -} - - -/// Prints a signed integer value. -/// -/// @param log_file Log file -/// @param p Pointer to the value -/// @param length Length of the value in bytes -static VOID -Dhp__PrintValueSigned( - FILE* log_file, - VOID* p, - ULONG64 length) -{ - if( length == sizeof(INT32) ) fprintf(log_file, "%I32d", *(INT32*)p); - else if( length == sizeof(INT64) ) fprintf(log_file, "%I64d", *(INT64*)p); - else if( length == sizeof(char) ) fprintf(log_file, "%d", *(signed char*)p); - else if( length == sizeof(short) ) fprintf(log_file, "%d", *(signed short*)p); - else if( length == sizeof(int) ) fprintf(log_file, "%d", *(signed int*)p); - else if( length == sizeof(long) ) fprintf(log_file, "%ld", *(signed long*)p); - else if( length == sizeof(long long) ) fprintf(log_file, "%lld", *(signed long long*)p); - else - { - fprintf(log_file, "<unexpected length %I64u>", length); - Dhp__PrintValueBytes(log_file, (BYTE*)p, length); - } -} - - -/// Prints a nul-terminated wide string value. -/// Checks if the memory can be read from. -/// -/// @param log_file Log file -/// @param str Target string -static VOID -Dhp__PrintValueCWideString( - FILE* log_file, - WCHAR* str) -{ - ULONG64 length = 0; - - // check if memory is readable - __try - { - while( str[length] != L'\0' ) - ++length; - } - __except( EXCEPTION_EXECUTE_HANDLER ) - { - if( length ) Dhp__PrintValueWideChars(log_file, str, length*sizeof(WCHAR), TRUE); // print readable part - fprintf(log_file, "<invalid memory>"); - return; - } - - // print string - Dhp__PrintValueWideChars(log_file, str, length*sizeof(WCHAR), TRUE); -} - - -/// Prints a nul-terminated string value. -/// Checks if the memory can be read from. -/// -/// @param log_file Log file -/// @param str Target string -static VOID -Dhp__PrintValueCString( - FILE* log_file, - char* str) -{ - ULONG64 length = 0; - - assert( log_file != NULL ); - - // check if memory is readable - __try - { - while( str[length] != '\0' ) - ++length; - } - __except( EXCEPTION_EXECUTE_HANDLER ) - { - if( length ) Dhp__PrintValueChars(log_file, str, length*sizeof(char), TRUE); // print readable part - fprintf(log_file, "<invalid memory>"); - return; - } - - // print string - Dhp__PrintValueChars(log_file, str, length*sizeof(char), TRUE); -} - - -// forward declaration of Dhp__PrintDataContents -static VOID Dhp__PrintDataContents(DWORD typeIndex, PVOID pVariable, InterData* interData); - - -/// Prints the value of the data symbol. -/// Checks if the memory can be read from. -/// -/// @param typeIndex Type index of the symbol -/// @param symtag Symbol tag -/// @param pVariable Address to the symbol contents -/// @param pInterData Inter data -static VOID -Dhp__PrintDataValue( - DWORD typeIndex, - DWORD symtag, - PVOID pVariable, - InterData* pInterData) -{ - // inter data - FILE* log_file; - DWORD64 modBase; - HANDLE hProcess; - // - ULONG64 length = 0; - DWORD basetype; - BOOL isValid = TRUE; - - assert( pInterData != NULL ); - log_file = pInterData->log_file; - modBase = pInterData->modBase; - hProcess = pInterData->hProcess; - - if( !SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_LENGTH, &length) ) - { - fprintf(log_file, "<unknown data length>"); - return; - } - - // check if memory is readable - __try - { - BYTE* p = (BYTE*)pVariable; - ULONG i; - BYTE b = 0; - for( i = 0; i < length; ++i ) - b += p[i]; // add to make sure it's not optimized out in release mode - } - __except( EXCEPTION_EXECUTE_HANDLER ) - { - fprintf(log_file, "<invalid memory>"); - return; - } - - switch( symtag ) - { - case SymTagBaseType: - { - if( !SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_BASETYPE, &basetype) ) - { - fprintf(log_file, "<basetype not found>"); - Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - break; - } - switch( basetype ) - { - case btInt: - case btLong: - Dhp__PrintValueSigned(log_file, pVariable, length); - break; - case btUInt: - case btULong: - Dhp__PrintValueUnsigned(log_file, pVariable, length); - break; - case btFloat: - Dhp__PrintValueFloat(log_file, pVariable, length); - break; - case btChar: - { - if( length == sizeof(char) ) fprintf(log_file, "%u ", *(unsigned char*)pVariable); - Dhp__PrintValueChars(log_file, (char*)pVariable, length, FALSE); - } - break; - case btWChar: - { - if( length == sizeof(WCHAR) ) fprintf(log_file, "%u ", *(WCHAR*)pVariable); - Dhp__PrintValueWideChars(log_file, (WCHAR*)pVariable, length, FALSE); - } - break; - case btVoid: - if( length > 0 ) Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - break; - default: - fprintf(log_file, "<TODO value of basetype %d>", basetype); - Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - break; - } - } - break; - case SymTagEnum: - Dhp__PrintValueHex(log_file, pVariable, length); - break; - case SymTagPointerType: - { - DWORD childTypeIndex; - DWORD childSymtag; - - fprintf(log_file, "0x%p", *(void**)pVariable); - if( SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_TYPE, &childTypeIndex) && - SymGetTypeInfo_(hProcess, modBase, childTypeIndex, TI_GET_SYMTAG, &childSymtag) && - childSymtag != SymTagPointerType ) - { - DWORD childBasetype; - - // child isn't a pointer, print the contents - fprintf(log_file, " "); - if( childSymtag == SymTagBaseType && - SymGetTypeInfo_(hProcess, modBase, childTypeIndex, TI_GET_BASETYPE, &childBasetype) && - (childBasetype == btChar || childBasetype == btWChar) ) - { - // string or wide string - if( childBasetype == btChar ) Dhp__PrintValueCString(log_file, *(char**)pVariable); - else if( childBasetype == btWChar ) Dhp__PrintValueCWideString(log_file, *(WCHAR**)pVariable); - else fprintf(log_file, "<unexpected child basetype %d>", childBasetype); - break; - } - Dhp__PrintDataValue(childTypeIndex, childSymtag, *(PVOID*)pVariable, pInterData); - } - } - break; - case SymTagArrayType: - { - DWORD childTypeIndex; - DWORD childSymtag; - DWORD count; - DWORD i; - - if( !SymGetTypeInfo_( hProcess, modBase, typeIndex, TI_GET_TYPE, &childTypeIndex) ) - { - fprintf(log_file, "<child type not found>"); - Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - break; - } - if( !SymGetTypeInfo_( hProcess, modBase, childTypeIndex, TI_GET_SYMTAG, &childSymtag) ) - { - fprintf(log_file, "<child symtag not found>"); - Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - break; - } - if( !SymGetTypeInfo_( hProcess, modBase, typeIndex, TI_GET_COUNT, &count) ) - { - fprintf(log_file, "<count not found>"); - Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - break; - } - // print values - fprintf(log_file, "{"); - for( i = 0; i < count; ++i ) - { - BYTE* pData = pVariable; - pData += i*(length/count); - if( i > 0 ) fprintf(log_file, ","); - Dhp__PrintDataValue(childTypeIndex, childSymtag, pData, pInterData); - } - fprintf(log_file, "}"); - } - break; - default: -#if 0 - {//## TODO show children of structs/unions - TI_FINDCHILDREN_PARAMS* children; - DWORD childCount; - DWORD i; - - // count children - if( !SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_CHILDRENCOUNT, &childCount) ) - { - fprintf(log_file, "<child count not found>"); - Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - break; - } - - // Prepare to get an array of "TypeIds", representing each of the children. - // SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a - // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this. - children = (TI_FINDCHILDREN_PARAMS*)LocalAlloc(LMEM_FIXED, sizeof(TI_FINDCHILDREN_PARAMS)+childCount*sizeof(ULONG)); - children->Count = childCount; - children->Start= 0; - - // Get the array of TypeIds, one for each child type - if( !SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_FINDCHILDREN, &children) ) - { - fprintf(log_file, "<children not found>"); - Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - LocalFree(children); - return; - } - - // Iterate through each of the children - fprintf(log_file, "{"); - for( i = 0; i < childCount; ++i ) - { - DWORD childOffset; - DWORD childTypeid; - WCHAR* childName; - DWORD_PTR pData; - - if( i > 0 ) fprintf(log_file, ","); - - // Get the offset of the child member, relative to its parent - if( !SymGetTypeInfo_(hProcess, modBase, children->ChildId[i], TI_GET_OFFSET, &childOffset) ) - { - fprintf(log_file, "<child offset not found>"); - continue; - } - - // Get the real "TypeId" of the child. - if( !SymGetTypeInfo_(hProcess, modBase, children->ChildId[i], TI_GET_TYPEID, &childTypeid) ) - { - fprintf(log_file, "<child typeid not found>"); - continue; - } - - // Calculate the address of the member - pData = (DWORD_PTR)pVariable; - pData += childOffset; - - // print name of the child - if( !SymGetTypeInfo_(hProcess, modBase, childTypeid, TI_GET_SYMNAME, &childName) ) - { - fprintf(log_file, "<child symname not found>"); - continue; - } - fprintf(log_file, "%ws=", childName); - LocalFree(childName); - - // print contents of the child - Dhp__PrintDataContents(childTypeid, (PVOID)pData, interData); - } - fprintf(log_file, "}"); - - LocalFree(children); - } -#endif - Dhp__PrintValueBytes(log_file, (BYTE*)pVariable, length); - break; - } -} - - -/// Prints the contents of the data symbol. (type and value) -/// -/// @param typeIndex Type index of the symbol -/// @param pVariable Address of the symbol contents -/// @param pInterData Inter data -static VOID -Dhp__PrintDataContents( - DWORD typeIndex, - PVOID pVariable, - InterData* pInterData) -{ - // inter data - FILE* log_file; - HANDLE hProcess; - DWORD64 modBase; - // - DWORD symtag; - - assert( pInterData != NULL ); - log_file = pInterData->log_file; - hProcess = pInterData->hProcess; - modBase = pInterData->modBase; - - if( SymGetTypeInfo_(hProcess, modBase, typeIndex, TI_GET_SYMTAG, &symtag) ) - { - // print type - Dhp__PrintTypeName(typeIndex, symtag, TRUE, pInterData); - // print value - Dhp__PrintDataValue(typeIndex, symtag, pVariable, pInterData); - } - else - fprintf(log_file, "<symtag not found>"); -} - - -/// Prints information about the data symbol. -/// -/// @param pSymInfo Symbol info -/// @param pInterData Inter data -static VOID -Dhp__PrintDataInfo( - PSYMBOL_INFO pSymInfo, - InterData* pInterData) -{ - // inter data - FILE* log_file; - STACKFRAME* pStackframe; - BOOL as_arg_list; - BOOL log_params; - BOOL log_locals; - BOOL log_globals; - int nr_of_var; - // my data - DWORD_PTR pVariable = 0; - enum{ UNKNOWN, PARAM, LOCAL, GLOBAL } scope = UNKNOWN; - - assert( pSymInfo != NULL ); - assert( pInterData != NULL ); - assert( pSymInfo->Tag == SymTagData ); - log_file = pInterData->log_file; - pStackframe = pInterData->pStackframe; - as_arg_list = pInterData->as_arg_list; - log_params = pInterData->log_params; - log_locals = pInterData->log_locals; - log_globals = pInterData->log_globals; - nr_of_var = pInterData->nr_of_var; - - // Determine the scope and address of the variable - if( pSymInfo->Flags & SYMFLAG_REGREL ) - { - pVariable = pStackframe->AddrFrame.Offset; - pVariable += (DWORD_PTR)pSymInfo->Address; - if( pSymInfo->Flags & SYMFLAG_PARAMETER ) - scope = PARAM; // parameter - else if( pSymInfo->Flags & SYMFLAG_LOCAL ) - { - scope = LOCAL; // local -#if defined(_M_IX86) - if( (LONG64)pSymInfo->Address > 0) scope = PARAM; // parameter as local (bug in DBGHELP 5.1) -#endif - } - } - else if( pSymInfo->Flags & SYMFLAG_REGISTER ) - { - scope = ( pSymInfo->Flags & SYMFLAG_PARAMETER ? PARAM : LOCAL ); // register, optimized out(?) - } - else - { - pVariable = (DWORD_PTR)pSymInfo->Address; - scope = GLOBAL; // It must be a global variable - } - - // check if we should to log the variable - if( (scope == PARAM && log_params) || - (scope == LOCAL && log_locals) || - (scope == GLOBAL && log_globals) ) - { - // print prefix and name - if( as_arg_list ) - fprintf(log_file, "%s%s=", (nr_of_var ? ", " : ""), pSymInfo->Name); - else - fprintf(log_file, "\t%s = ", pSymInfo->Name); - - // print value - if( !(pSymInfo->Flags & SYMFLAG_REGREL) && (pSymInfo->Flags & SYMF_REGISTER) ) - fprintf(log_file, "<value optimized out>"); - else - { - pInterData->modBase = pSymInfo->ModBase; - Dhp__PrintDataContents(pSymInfo->TypeIndex, (PVOID)pVariable, pInterData); - } - - // print postfix - if( !as_arg_list ) - fprintf(log_file, "\n"); - pInterData->nr_of_var = ++nr_of_var; - } -} - - -/// Prints information about the symbol. -/// -/// @param pSymInfo Symbol info -/// @param pInterData Inter data -static VOID -Dhp__PrintSymbolInfo( - PSYMBOL_INFO pSymInfo, - InterData* pInterData) -{ - assert( pSymInfo != NULL ); - assert( pInterData != NULL ); - - switch( pSymInfo->Tag ) - { - case SymTagData: Dhp__PrintDataInfo( pSymInfo, pInterData ); break; - default: /*fprintf(pInterData->log_file, "<unsupported symtag %d>", pSymInfo->Tag);*/ break; - } -} - - -/// Prints the details of one symbol to the log file. -/// Used as a callback for SymEnumSymbols. -/// -/// @param pSymInfo Symbol info -/// @param symSize Size of the symbol info structure -/// @param pData Inter data -static BOOL WINAPI -Dhp__EnumSymbolsCallback( - PSYMBOL_INFO pSymInfo, - ULONG symSize, - PVOID pData) -{ - if( pSymInfo == NULL ) - return TRUE; // try other symbols - - if( pData == NULL ) - { - printf("Dhp__EnumSymbolsCallback: pData is NULL\n"); - return FALSE; - } - - Dhp__PrintSymbolInfo(pSymInfo, (InterData*)pData); - return TRUE; -} - - -/// Prints the source code of the target line. -/// Searches for the target file in the original path, -/// in the last src folder of the original path (relative) -/// and in the current directory. -/// -/// @param filename Original source file -/// @param line Target line -/// @param log_file Log file -static VOID -Dhp__PrintSourceLine( - FILE* log_file, - char* filename, - DWORD line) -{ - char path[MAX_PATH*3]; - char pathBuffer[MAX_PATH+1]; - char* p; - - assert( filename != NULL ); - assert( log_file != NULL ); - - // generate search paths - strcpy(path, filename); // original path - p = strrchr(path, '\\'); - if( p ) - { - memcpy(p, ";\0", 2); - p = strstr(filename, "\\src\\"); - if( p ) - { - while( strstr(p+1, "\\src\\") ) - p = strstr(p+1, "\\src\\"); - strcat(path, p+1); // last src folder path - p = strrchr(path, '\\'); - memcpy(p, ";\0", 2); - } - filename = strrchr(filename, '\\')+1; - } - else - *path = '\0'; // no path - strcat(path, "."); // current directoy - - // search for file and line - if( SearchPathA(path, filename, NULL, MAX_PATH, pathBuffer, NULL) ) - { - char code[1024+1]; - DWORD i = 1; - FILE* fp; - - fp = fopen(pathBuffer, "rt"); - if( fp == NULL ) - return; - - code[1024] = '\0'; - while( fgets(code, 1024, fp) ) - { - if( i == line ) - {// found line - char* term = strchr(code, '\n'); - if( term && term != code && term[-1] == '\r' ) --term; - if( term ) *term = '\0'; - fprintf(log_file, "%d\t%s\n", line, code); - break; - } - if( strchr(code, '\n') ) - ++i; - } - fclose(fp); - } -} - - -/// Prints details of one function to the log file. -/// -/// @param interData Inter data -static VOID -Dhp__PrintFunctionDetails( - InterData* pInterData) -{ - // inter data - HANDLE hProcess; - STACKFRAME* pStackframe; - FILE* log_file; - int nr_of_frame; - // - PSYMBOL_INFO pSymbolInfo; - DWORD64 funcDisplacement=0; - IMAGEHLP_STACK_FRAME imagehlpStackFrame; - IMAGEHLP_LINE imagehlpLine; - DWORD lineDisplacement=0; - - assert( pInterData != NULL ); - hProcess = pInterData->hProcess; - pStackframe = pInterData->pStackframe; - log_file = pInterData->log_file; - nr_of_frame = pInterData->nr_of_frame; - - // frame info - fprintf(log_file, - "#%d 0x%p", - nr_of_frame, (void*)(DWORD_PTR)pStackframe->AddrPC.Offset); - - // restrict symbol enumeration to this frame only - ZeroMemory(&imagehlpStackFrame, sizeof(IMAGEHLP_STACK_FRAME)); - imagehlpStackFrame.InstructionOffset = pStackframe->AddrPC.Offset; - SymSetContext_(hProcess, &imagehlpStackFrame, 0); - - // function name and displacement - pSymbolInfo = (PSYMBOL_INFO)LocalAlloc(LMEM_FIXED, sizeof(SYMBOL_INFO)+1024); - pSymbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO); - pSymbolInfo->MaxNameLen = 1024; - if( SymFromAddr_(hProcess, pStackframe->AddrPC.Offset, &funcDisplacement, pSymbolInfo) == TRUE ) - { - fprintf(log_file, - " in %.1024s+0x%I64X (", - pSymbolInfo->Name, funcDisplacement); - - // log all function parameters - pInterData->as_arg_list = TRUE; - pInterData->log_params = TRUE; - pInterData->log_locals = FALSE; - pInterData->log_globals = FALSE; - pInterData->nr_of_var = 0; - SymEnumSymbols_(hProcess, 0, 0, Dhp__EnumSymbolsCallback, pInterData); - - fprintf(log_file, - ")"); - } - else - fprintf(log_file, - "in <unknown function>"); - - // find the source line for this function. - imagehlpLine.SizeOfStruct = sizeof(IMAGEHLP_LINE); - if( SymGetLineFromAddr_(hProcess, pStackframe->AddrPC.Offset, &lineDisplacement, &imagehlpLine) != 0 ) - { - char* filename = imagehlpLine.FileName; - DWORD line = imagehlpLine.LineNumber; - - fprintf(log_file, - " at %s:%d\n", - filename, line); - - Dhp__PrintSourceLine(log_file, filename, line); - } - else - fprintf(log_file, - "\n"); - - // log all function local variables - pInterData->as_arg_list = FALSE; - pInterData->log_params = FALSE; - pInterData->log_locals = TRUE; - pInterData->log_globals = FALSE; - pInterData->nr_of_var = 0; - SymEnumSymbols_(hProcess, 0, 0, Dhp__EnumSymbolsCallback, pInterData); - - pInterData->nr_of_frame = ++nr_of_frame; - LocalFree(pSymbolInfo); -} - - -/// Walks over the stack and prints all relevant information to the log file. -/// -/// @param context Exception context -/// @param log_file Log file -static VOID -Dhp__PrintStacktrace( - CONTEXT *context, - FILE *log_file) -{ - HANDLE hProcess = GetCurrentProcess(); - STACKFRAME stackframe; - DWORD machine; - CONTEXT ctx; - InterData interData; - int skip = 0; - int i; - - assert( log_file != NULL ); - - fprintf(log_file, - "\nStacktrace:\n"); - - // Use thread information - if not supplied. - if( context == NULL ) - { - // If no context is supplied, skip 1 frame - skip = 1; - - ctx.ContextFlags = CONTEXT_FULL; - if( GetThreadContext(GetCurrentThread(), &ctx) ) - context = &ctx; - } - - if( context == NULL ) - return; - - // Write the stack trace - ZeroMemory(&stackframe, sizeof(STACKFRAME)); - stackframe.AddrPC.Mode = AddrModeFlat; - stackframe.AddrStack.Mode = AddrModeFlat; - stackframe.AddrFrame.Mode = AddrModeFlat; -#if defined(_M_IX86) - machine = IMAGE_FILE_MACHINE_I386; - stackframe.AddrPC.Offset = context->Eip; - stackframe.AddrStack.Offset = context->Esp; - stackframe.AddrFrame.Offset = context->Ebp; -#else /* defined(_M_IX86) */ -#error FIXME add more processors -some compilers don't stop on #error, this line makes sure it errors out -#endif - - interData.hProcess = hProcess; - interData.log_file = log_file; - interData.pStackframe = &stackframe; - interData.nr_of_frame = 0; - for( i = 0; ; ++i ) - { - if( !StackWalk_(machine, hProcess, GetCurrentThread(), - &stackframe, context, NULL, SymFunctionTableAccess_, - SymGetModuleBase_, NULL)) - { - break; - } - - if( i >= skip ) - { - // Check that the address is not zero. - // Sometimes StackWalk returns TRUE with a frame of zero. - if( stackframe.AddrPC.Offset != 0 ) - Dhp__PrintFunctionDetails(&interData); - } - } -} - - -typedef BOOL (WINAPI *ISDEBUGGERPRESENT)(void); -/// Checks if a debugger is attached to this process -/// -/// @return TRUE is a debugger is present -static BOOL -Dhp__IsDebuggerPresent() -{ - HANDLE kernel32_dll; - ISDEBUGGERPRESENT IsDebuggerPresent_; - BOOL result; - - kernel32_dll = LoadLibraryA("kernel32.dll"); - if( kernel32_dll == NULL ) - return FALSE; - - IsDebuggerPresent_ = (ISDEBUGGERPRESENT)GetProcAddress(kernel32_dll, "IsDebuggerPresent"); - if( IsDebuggerPresent_ ) - result = IsDebuggerPresent_(); - else - result = FALSE; - - FreeLibrary(kernel32_dll); - - return result; -} - - -/// Loads the dbghelp.dll library. -/// -/// @return TRUE is sucessfull -static BOOL -Dhp__LoadDbghelpDll() -{ - dbghelp_dll = LoadLibraryA(DBGHELP_DLL); - if( dbghelp_dll != INVALID_HANDLE_VALUE ) - { - DWORD opts; - - // load the functions - MiniDumpWriteDump_ = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelp_dll, "MiniDumpWriteDump"); - SymInitialize_ = (SYMINITIALIZE)GetProcAddress(dbghelp_dll, "SymInitialize"); - SymSetOptions_ = (SYMSETOPTIONS)GetProcAddress(dbghelp_dll, "SymSetOptions"); - SymGetOptions_ = (SYMGETOPTIONS)GetProcAddress(dbghelp_dll, "SymGetOptions"); - SymCleanup_ = (SYMCLEANUP)GetProcAddress(dbghelp_dll, "SymCleanup"); - SymGetTypeInfo_ = (SYMGETTYPEINFO)GetProcAddress(dbghelp_dll, "SymGetTypeInfo"); - SymGetLineFromAddr_ = (SYMGETLINEFROMADDR)GetProcAddress(dbghelp_dll, "SymGetLineFromAddr"); - SymEnumSymbols_ = (SYMENUMSYMBOLS)GetProcAddress(dbghelp_dll, "SymEnumSymbols"); - SymSetContext_ = (SYMSETCONTEXT)GetProcAddress(dbghelp_dll, "SymSetContext"); - SymFromAddr_ = (SYMFROMADDR)GetProcAddress(dbghelp_dll, "SymFromAddr"); - StackWalk_ = (STACKWALK)GetProcAddress(dbghelp_dll, "StackWalk"); - SymFunctionTableAccess_ = (SYMFUNCTIONTABLEACCESS)GetProcAddress(dbghelp_dll, "SymFunctionTableAccess"); - SymGetModuleBase_ = (SYMGETMODULEBASE)GetProcAddress(dbghelp_dll, "SymGetModuleBase"); - - if( MiniDumpWriteDump_ && - SymInitialize_ && SymSetOptions_ && SymGetOptions_ && - SymCleanup_ && SymGetTypeInfo_ && SymGetLineFromAddr_ && - SymEnumSymbols_ && SymSetContext_ && SymFromAddr_ && StackWalk_ && - SymFunctionTableAccess_ && SymGetModuleBase_ ) - { - // initialize the symbol loading code - opts = SymGetOptions_(); - - // Set the 'load lines' option to retrieve line number information. - // Set the 'deferred loads' option to map the debug info in memory only when needed. - SymSetOptions_(opts | SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS); - - // Initialize the dbghelp DLL with the default path and automatic - // module enumeration (and loading of symbol tables) for this process. - SymInitialize_(GetCurrentProcess(), NULL, TRUE); - - return TRUE; - } - } - - if( dbghelp_dll ) - { - FreeLibrary(dbghelp_dll); - dbghelp_dll = NULL; - } - - return FALSE; -} - - -/// Unloads the dbghelp.dll library. -static VOID -Dhp__UnloadDbghlpDll() -{ - SymCleanup_(GetCurrentProcess()); - - FreeLibrary(dbghelp_dll); - dbghelp_dll = NULL; -} - - -/// Creates the report and minidump files. -/// Puts the resulting pathnames in the arguments. -/// The buffers must be at least MAX_PATH+1 in size. -/// -/// @param out_lpszLogFileName Buffer for the report filename -/// @param out_lpszDmpFileName Buffer for the minidump filename -/// @return TRUE if the files were created -static BOOL -Dhp__CreateFiles( - char* out_logFileName, - char* out_dmpFileName) -{ -#define LEN_TIMESTAMP 14 // "YYYYMMDDhhmmss" -#define LEN_EXT 4 // ".rpt" or ".dmp" - char baseFileName[MAX_PATH+1]; - char timestamp[LEN_TIMESTAMP+1]; - FILE* fp; - time_t now; - - // Generate base filename for the report/minidump - ZeroMemory(baseFileName, sizeof(baseFileName)); - if( GetModuleFileName(NULL, baseFileName, MAX_PATH-LEN_TIMESTAMP-LEN_EXT) ) - { - char* pTerm = strrchr(baseFileName, '\\'); - if( pTerm == NULL ) pTerm = baseFileName; - pTerm = strrchr(pTerm, '.'); - if( pTerm ) *pTerm = '\0'; // remove extension - } - else if( GetTempPathA(MAX_PATH-6-LEN_TIMESTAMP-LEN_EXT, baseFileName) ) - {// in temp folder - strcat(baseFileName, DBG_DEFAULT_FILENAME); - } - else - {// in current folder - strcpy(baseFileName, DBG_DEFAULT_FILENAME); - } - - time(&now); -#if 0 - szTimestamp[0] = '\0'; -#else - strftime(timestamp, sizeof(timestamp), "%Y%m%d%H%M%S", localtime(&now)); -#endif - timestamp[LEN_TIMESTAMP] = '\0'; - - sprintf(out_logFileName, "%s%s.rpt", baseFileName, timestamp); - fp = fopen(out_logFileName, "w"); - if( fp == NULL ) - return FALSE; // failed to create log file - fclose(fp); - - sprintf(out_dmpFileName, "%s%s.dmp", baseFileName, timestamp); - fp = fopen(out_dmpFileName, "w"); - if( fp == NULL) - return FALSE; // failed to create dump file - fclose(fp); - - return TRUE; // success -#undef LEN_EXT -#undef LEN_TIMESTAMP -} - - -/// Unhandled exception handler. Where the magic starts... ;D -/// -/// @param ptrs Exception information -/// @return What to do with the exception -LONG WINAPI -Dhp__UnhandledExceptionFilter(PEXCEPTION_POINTERS ptrs) -{ - char szLogFileName[MAX_PATH+1]; - char szDmpFileName[MAX_PATH+1]; - FILE* log_file; - - // check if the crash handler was already loaded (crash while handling the crash) - if( dbghelp_dll != INVALID_HANDLE_VALUE ) - return EXCEPTION_CONTINUE_SEARCH; - - // don't log anything if we're running inside a debugger ... - if( Dhp__IsDebuggerPresent() == TRUE ) - return EXCEPTION_CONTINUE_SEARCH; - - // ... or if we can't load dbghelp.dll ... - if( Dhp__LoadDbghelpDll() == FALSE ) - return EXCEPTION_CONTINUE_SEARCH; - - // ... or if we can't create the log files - if( Dhp__CreateFiles(szLogFileName, szDmpFileName) == FALSE ) - return EXCEPTION_CONTINUE_SEARCH; - - // open log file - log_file = fopen(szLogFileName, "wt"); - - // print information about the process - Dhp__PrintProcessInfo( - ptrs ? ptrs->ExceptionRecord : NULL, - ptrs ? ptrs->ContextRecord : NULL, - log_file); - - // print the stacktrace - Dhp__PrintStacktrace( - ptrs ? ptrs->ContextRecord : NULL, - log_file); - - // write the minidump file and use the callback to print the list of modules to the log file - Dhp__WriteMinidumpFile( - szDmpFileName, - ptrs, - Dhp__PrintModuleInfoCallback, - log_file); - - fclose(log_file); - - Dhp__UnloadDbghlpDll(); - - // inform the user - fprintf(stderr, - "\n" - "This application has halted due to an unexpected error.\n" - "A crash report and minidump file were saved to disk, you can find them here:\n" - "%s\n" - "%s\n" - DBG_EXTENDED_INFORMATION - "\n" - "NOTE: The crash report and minidump files can contain sensitive information\n" - "(filenames, partial file content, usernames and passwords etc.)\n", - szLogFileName, - szDmpFileName); - - // terminate the application - return EXCEPTION_EXECUTE_HANDLER; -} - - - -///////////////////////////////////////////////////////////////////// -// DLL stuff -#if !defined(DBG_EMBEDDED) - - -/// Previous exception filter. -static LPTOP_LEVEL_EXCEPTION_FILTER previousFilter; - - -#if defined(__GNUC__) -// GNU : define DLL load/unload functions -static void Dhp__OnStartup(void) __attribute__((constructor)); -static void Dhp__OnExit(void) __attribute__((destructor)); -#endif /* defined(__GNUC__) */ - - -/// Installs as the unhandled exception handler. -void Dhp__OnStartup(void) -{ - // Install the unhandled exception filter function - previousFilter = SetUnhandledExceptionFilter(Dhp__UnhandledExceptionFilter); -} - - -/// Uninstalls the handler. -void Dhp__OnExit(void) -{ - SetUnhandledExceptionFilter(previousFilter); -} - - -#if !defined(__GNUC__) -// Windows : invoke DLL load/unload functions -BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) -{ - switch( dwReason ) - { - case DLL_PROCESS_ATTACH: Dhp__OnStartup(); break; - case DLL_PROCESS_DETACH: Dhp__OnExit(); break; - } - return TRUE; -} -#endif /* !defined(__GNUC__) */ - - - -#endif /* !defined(DBG_EMBEDDED) */ - - - -#endif /* _WIN32 */ diff --git a/src/plugins/dbghelpplug.rc b/src/plugins/dbghelpplug.rc deleted file mode 100644 index 83a68d66c..000000000 --- a/src/plugins/dbghelpplug.rc +++ /dev/null @@ -1,54 +0,0 @@ -// BC++ has all the necessary preprocessor macros defined automatically -#if !defined(__BORLANDC__) -#include "winres.h" -#endif // !defined(__BORLANDC__) - -#define VER_FILEVERSION 1,0,0,2 -#define VER_FILEVERSION_STR "1.0.0.2\0" - -#define VER_PRODUCTVERSION 1,0,0,2 -#define VER_PRODUCTVERSION_STR "1.0.0.2\0" - -#if defined(DEBUG) || defined(_DEBUG) -#define VER_DEBUG 0 -#else -#define VER_DEBUG VS_FF_DEBUG -#endif - -#define VER_COMMENTS_STR "Registers as the unhandled exception handler. Generates reports and minidumps.\0" -#define VER_COMPANYNAME_STR "eAthena\0" -#define VER_FILEDESCRIPTION_STR "Stackdump Plugin by eAthena\0" -#define VER_INTERNALNAME_STR "dbghelpplug\0" -#define VER_LEGALCOPYRIGHT_STR "Copyright (C) 2008\0" -#define VER_ORIGINALFILENAME_STR "dbghelpplug.dll\0" -#define VER_PRODUCTNAME_STR "dbghelpplug\0" - -VS_VERSION_INFO VERSIONINFO -FILEVERSION VER_FILEVERSION -PRODUCTVERSION VER_PRODUCTVERSION -FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -FILEFLAGS VER_DEBUG -FILEOS (VOS_NT|VOS__WINDOWS32) -FILETYPE VFT_DLL -FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - BEGIN - VALUE "Comments", VER_COMMENTS_STR - VALUE "CompanyName", VER_COMPANYNAME_STR - VALUE "FileDescription", VER_FILEDESCRIPTION_STR - VALUE "FileVersion", VER_FILEVERSION_STR - VALUE "InternalName", VER_INTERNALNAME_STR - VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR - VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR - VALUE "ProductName", VER_PRODUCTNAME_STR - VALUE "ProductVersion", VER_PRODUCTVERSION_STR - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END diff --git a/src/plugins/pid.c b/src/plugins/pid.c deleted file mode 100644 index 48013e3eb..000000000 --- a/src/plugins/pid.c +++ /dev/null @@ -1,53 +0,0 @@ - -#include <stdio.h> -#include <string.h> - -#if !defined _WIN32 || defined MINGW - #include <unistd.h> // getpid(), unlink() -#else - #include <windows.h> - #define getpid GetCurrentProcessId -#endif - -#include "../common/plugin.h" - -PLUGIN_INFO = { - "ProcessId", - PLUGIN_ALL, - "1.0", - PLUGIN_VERSION, - "Logs the process ID" -}; - -PLUGIN_EVENTS_TABLE = { - { "pid_create", "Plugin_Init" }, - { "pid_delete", "Plugin_Final" }, - { NULL, NULL } -}; - -char pid_file[256]; -char *server_name; - -void pid_create () -{ - FILE *fp; - int len; - - IMPORT_SYMBOL(server_name, 1); - len = strlen(server_name); - strcpy(pid_file, server_name); - if(len > 4 && pid_file[len - 4] == '.') { - pid_file[len - 4] = 0; - } - strcat(pid_file, ".pid"); - fp = fopen(pid_file, "w"); - if (fp) { - fprintf(fp, "%d", getpid()); - fclose(fp); - } -} - -void pid_delete () -{ - unlink(pid_file); -} diff --git a/src/plugins/pid.def b/src/plugins/pid.def deleted file mode 100644 index a70cf8127..000000000 --- a/src/plugins/pid.def +++ /dev/null @@ -1,7 +0,0 @@ -EXPORTS - plugin_info DATA - plugin_event_table DATA - plugin_call_table DATA - - pid_create - pid_delete diff --git a/src/plugins/sample.c b/src/plugins/sample.c deleted file mode 100644 index 39e95752b..000000000 --- a/src/plugins/sample.c +++ /dev/null @@ -1,77 +0,0 @@ -// Sample Athena plugin - -#include <stdio.h> -#include <string.h> -#include "../common/plugin.h" - -////// Plugin information //////// -// -PLUGIN_INFO = { -// change only the following area - "Test", // Plugin name - PLUGIN_ALL, // Which servers is this plugin for - "0.1", // Plugin version - PLUGIN_VERSION, // Minimum plugin engine version to run - "A sample plugin" // Short description of plugin -}; - -////// Plugin event list ////////// -// Format: <plugin function>,<event name> -// All registered functions to a event gets executed -// (In descending order) when its called. -// Multiple functions can be called by multiple events too, -// So it's up to your creativity ^^ -// -PLUGIN_EVENTS_TABLE = { -// change only the following area - { "test_me", "Plugin_Test" }, // when the plugin is tested for compatibility - { "do_init", "Plugin_Init" }, // when plugins are loaded - { "do_final", "Plugin_Final" }, // when plugins are unloaded - { "some_function", "some_event" }, - { "some_function", "another_event" }, - { NULL, NULL } -}; - -///// Variables ///// -char *server_type; -char *server_name; - -//////// Plugin functions ////////// -int do_init () -{ - // import symbols from the server - IMPORT_SYMBOL(server_type, 0); - IMPORT_SYMBOL(server_name, 1); - - printf ("Server type is "); - switch (*server_type) { - case PLUGIN_LOGIN: printf ("Login\n"); break; - case PLUGIN_CHAR: printf ("Char\n"); break; - case PLUGIN_MAP: printf ("Map\n"); break; - } - printf ("Filename is %s\n", server_name); - - return 1; -} - -int do_final () -{ - printf ("Bye world\n"); - - return 1; -} - -int some_function () -{ - printf ("Some function\n"); - return 0; -} - -// return 1 if the testing passes, otherwise 0 -// (where the plugin will be deactivated) -int test_me () -{ - if (1 + 1 == 2) - return 1; - return 0; -} diff --git a/src/plugins/sample.def b/src/plugins/sample.def deleted file mode 100644 index f5c4af652..000000000 --- a/src/plugins/sample.def +++ /dev/null @@ -1,11 +0,0 @@ -EXPORTS - ; common exports - plugin_info DATA - plugin_event_table DATA - plugin_call_table DATA - - ; plugin-specific exports - test_me - do_init - do_final - some_function diff --git a/src/plugins/sig.c b/src/plugins/sig.c deleted file mode 100644 index 04d07a496..000000000 --- a/src/plugins/sig.c +++ /dev/null @@ -1,208 +0,0 @@ -// $Id: sig.c 1 2005-6-13 3:17:17 PM Celestia $ - -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#define __USE_GNU // required to enable strsignal on some platforms -#include <string.h> -#include <time.h> -#include "../common/plugin.h" - -PLUGIN_INFO = { - "Signals", - PLUGIN_CORE, - "1.1", - PLUGIN_VERSION, - "Handles program signals" -}; - -PLUGIN_EVENTS_TABLE = { - { "sig_init", "Plugin_Init" }, - { "sig_final", "Plugin_Final" }, - { NULL, NULL } -}; - -////////////////////////////////////// - -#if defined(_WIN32) || defined(MINGW) - int sig_init() - { - printf("sig: This plugin is not supported - Enable 'exchndl' instead!\n"); - return 0; - } - int sig_final() { return 0; } -#elif defined (__NETBSD__) || defined (__FREEBSD__) - int sig_init() - { - printf("sig: This plugin is not supported!\n"); - return 0; - } - int sig_final() { return 0; } -#else - -////////////////////////////////////// - -#if !defined(CYGWIN) - #include <execinfo.h> -#endif - -const char* (*getrevision)(); -unsigned long (*getuptime)(); -char *server_name; -int crash_flag = 0; - -int sig_final (); - -// by Gabuzomeu -// This is an implementation of signal() using sigaction() for portability. -// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced -// Programming in the UNIX Environment_. -// - -#ifndef POSIX -#define compat_signal(signo, func) signal(signo, func) -#else -sigfunc *compat_signal(int signo, sigfunc *func) -{ - struct sigaction sact, oact; - - sact.sa_handler = func; - sigemptyset(&sact.sa_mask); - sact.sa_flags = 0; -#ifdef SA_INTERRUPT - sact.sa_flags |= SA_INTERRUPT; /* SunOS */ -#endif - - if (sigaction(signo, &sact, &oact) < 0) - return (SIG_ERR); - - return (oact.sa_handler); -} -#endif - -/*========================================= - * Dumps the stack using glibc's backtrace - *----------------------------------------- - */ -#ifdef CYGWIN - #define FOPEN_ freopen - #ifdef __cplusplus - extern "C" void cygwin_stackdump(); - #else - extern void cygwin_stackdump(); - #endif - -#else - #define FOPEN_(fn,m,s) fopen(fn,m) -#endif -void sig_dump(int sn) -{ - FILE *fp; - char file[256]; - int no = 0; - - crash_flag = 1; - // search for a usable filename - do { - sprintf (file, "log/%s%04d.stackdump", server_name, ++no); - } while((fp = fopen(file,"r")) && (fclose(fp), no < 9999)); - // dump the trace into the file - - if ((fp = FOPEN_(file, "w", stderr)) != NULL) { - const char *revision; - #ifndef CYGWIN - void* array[20]; - char **stack; - size_t size; - #endif - - printf ("sig: Dumping stack to '%s'...\n", file); - if ((revision = getrevision()) != NULL) - fprintf(fp, "Version: svn%s \n", revision); - fprintf(fp, "Exception: %s \n", strsignal(sn)); - fflush (fp); - - #ifdef CYGWIN - cygwin_stackdump (); - #else - fprintf(fp, "Stack trace:\n"); - size = backtrace (array, 20); - stack = backtrace_symbols (array, size); - for (no = 0; no < size; no++) { - fprintf(fp, "%s\n", stack[no]); - } - fprintf(fp,"End of stack trace\n"); - free(stack); - #endif - - printf("sig: %s Saved.\n", file); - fflush(stdout); - fclose(fp); - } - - sig_final(); // Log our uptime - // Pass the signal to the system's default handler - compat_signal(sn, SIG_DFL); - raise(sn); -} - -/*========================================= - * Shutting down (Program did not crash ^^) - * - Log our current up time - *----------------------------------------- - */ -int sig_final () -{ - time_t curtime; - char curtime2[24]; - FILE *fp; - long seconds = 0, day = 24*60*60, hour = 60*60, - minute = 60, days = 0, hours = 0, minutes = 0; - - fp = fopen("log/uptime.log","a"); - if (fp) { - time(&curtime); - strftime(curtime2, 24, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - - seconds = getuptime(); - days = seconds/day; - seconds -= (seconds/day>0)?(seconds/day)*day:0; - hours = seconds/hour; - seconds -= (seconds/hour>0)?(seconds/hour)*hour:0; - minutes = seconds/minute; - seconds -= (seconds/minute>0)?(seconds/minute)*minute:0; - - fprintf(fp, "%s: %s %s - %ld days, %ld hours, %ld minutes, %ld seconds.\n", - curtime2, server_name, (crash_flag ? "crashed" : "uptime"), - days, hours, minutes, seconds); - fclose(fp); - } - - return 1; -} - -/*========================================= - * Register the signal handlers - *----------------------------------------- - */ -int sig_init () -{ - void (*func)(int) = sig_dump; -#ifdef CYGWIN // test if dumper is enabled - char *buf = getenv ("CYGWIN"); - if (buf && strstr(buf, "error_start") != NULL) - func = SIG_DFL; -#endif - - IMPORT_SYMBOL(server_name, 1); - IMPORT_SYMBOL(getrevision, 6); - IMPORT_SYMBOL(getuptime, 11); - - compat_signal(SIGSEGV, func); - compat_signal(SIGFPE, func); - compat_signal(SIGILL, func); - compat_signal(SIGBUS, func); - - return 1; -} -#endif |