diff options
-rw-r--r-- | compile.bat | 4 | ||||
-rw-r--r-- | src/hook.c | 16 | ||||
-rw-r--r-- | src/hook.h | 4 | ||||
-rw-r--r-- | src/sst.c | 28 | ||||
-rw-r--r-- | test/hook.test.c | 3 |
5 files changed, 48 insertions, 7 deletions
diff --git a/compile.bat b/compile.bat index fa631b1..a96da7a 100644 --- a/compile.bat +++ b/compile.bat @@ -93,8 +93,8 @@ if "%dbg%"=="1" ( ) else (
set clibs=-lmsvcrt -lvcruntime -lucrt
)
-%CC% -shared -flto %ldflags% -Wl,/IMPLIB:.build/sst.lib,/Brepro,/nodefaultlib:libcmt ^
--L.build %clibs% -luser32 -ladvapi32 -lshlwapi -ld3d9 -ltier0 -lvstdlib -o sst.dll%objs% .build/dll.res || exit /b
+%CC% -shared -flto %ldflags% -Wl,/IMPLIB:.build/sst.lib,/Brepro,/nodefaultlib ^
+-L.build %clibs% -lkernel32 -luser32 -ladvapi32 -lshlwapi -ld3d9 -ltier0 -lvstdlib -o sst.dll%objs% .build/dll.res || exit /b
:: get rid of another useless file (can we just not create this???)
del .build\sst.lib
@@ -29,14 +29,20 @@ #if defined(_WIN32) && !defined(_WIN64) +#if defined(__GNUC__) || defined(__clang__) __attribute__((aligned(4096))) +#elif defined(_MSC_VER) +__declspec(align(4096)) +#else +#error no way to align stuff! +#endif static uchar trampolines[4096]; static uchar *nexttrampoline = trampolines; -__attribute__((constructor)) -static void setrwx(void) { - // PE doesn't support rwx sections, not sure about ELF. Eh, just hack it in - // a constructor instead. If this fails and we segfault later, too bad! - os_mprot(trampolines, sizeof(trampolines), PAGE_EXECUTE_READWRITE); + +bool hook_init(void) { + // PE doesn't support rwx sections, not sure about ELF. Meh, just set it + // here instead. + return os_mprot(trampolines, sizeof(trampolines), PAGE_EXECUTE_READWRITE); } void *hook_inline(void *func_, void *target) { @@ -17,8 +17,12 @@ #ifndef INC_HOOK_H #define INC_HOOK_H +#include <stdbool.h> + #include "intdefs.h" +bool hook_init(void); + /* * Replaces a vtable entry with a target function and returns the original * function. @@ -198,6 +198,11 @@ static bool already_loaded = false, skip_unload = false; #define RGBA(r, g, b, a) (&(struct con_colour){(r), (g), (b), (a)}) +// auto-update message. see below in do_featureinit() +static const char *updatenotes = "\ +* various internal cleanup\n\ +"; + static void do_featureinit(void) { has_autojump = autojump_init(); has_demorec = demorec_init(); @@ -217,6 +222,24 @@ static void do_featureinit(void) { LONGNAME " v" VERSION " successfully loaded"); con_colourmsg(RGBA(255, 255, 255, 255), " for game "); con_colourmsg(RGBA(0, 255, 255, 255), "%s\n", gameinfo_title); + + // if we're autoloaded and the external autoupdate script downloaded a new + // version, let the user know about the cool new stuff! + if (getenv("SST_UPDATED")) { + // avoid displaying again if we're unloaded and reloaded in one session +#ifdef _WIN32 + SetEnvironmentVariableA("SST_UPDATED", 0); +#else + unsetenv("SST_UPDATED"); +#endif + struct con_colour gold = {255, 210, 0, 255}; + struct con_colour white = {255, 255, 255, 255}; + con_colourmsg(&white, "\n" NAME " was just "); + con_colourmsg(&gold, "UPDATED"); + con_colourmsg(&white, " to version "); + con_colourmsg(&gold, "%s", VERSION); + con_colourmsg(&white, "!\n\nNew in this version:\n%s\n", updatenotes); + } } static void *vgui; @@ -268,6 +291,11 @@ e: con_warn("!!! SOME FEATURES MAY BE BROKEN !!!\n"); } static bool do_load(ifacefactory enginef, ifacefactory serverf) { + if (!hook_init()) { + errmsg_warnsys("couldn't set up memory for function hooking"); + return false; + } + factory_engine = enginef; factory_server = serverf; if (!engineapi_init(ifacever)) return false; diff --git a/test/hook.test.c b/test/hook.test.c index b2e841c..7cbfd15 100644 --- a/test/hook.test.c +++ b/test/hook.test.c @@ -33,12 +33,14 @@ static int other_hook(int a, int b) { } TEST("Inline hooks should be able to wrap the original function") { + if (!hook_init()) return false; orig_some_function = hook_inline(&some_function, &some_hook); if (!orig_some_function) return false; return some_function(5, 5) == 15; } TEST("Inline hooks should be removable again") { + if (!hook_init()) return false; orig_some_function = hook_inline(&some_function, &some_hook); if (!orig_some_function) return false; unhook_inline(orig_some_function); @@ -46,6 +48,7 @@ TEST("Inline hooks should be removable again") { } TEST("Multiple functions should be able to be inline hooked at once") { + if (!hook_init()) return false; orig_some_function = hook_inline(&some_function, &some_hook); if (!orig_some_function) return false; |