summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compile.bat4
-rw-r--r--src/hook.c16
-rw-r--r--src/hook.h4
-rw-r--r--src/sst.c28
-rw-r--r--test/hook.test.c3
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
diff --git a/src/hook.c b/src/hook.c
index bca226d..8465fbe 100644
--- a/src/hook.c
+++ b/src/hook.c
@@ -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) {
diff --git a/src/hook.h b/src/hook.h
index e432eb7..ff1acff 100644
--- a/src/hook.h
+++ b/src/hook.h
@@ -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.
diff --git a/src/sst.c b/src/sst.c
index 2ba4e9e..b7298ef 100644
--- a/src/sst.c
+++ b/src/sst.c
@@ -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;