diff options
-rw-r--r-- | compile | 5 | ||||
-rw-r--r-- | compile.bat | 7 | ||||
-rw-r--r-- | src/build/mkgamedata.c | 2 | ||||
-rw-r--r-- | src/demorec.c | 2 | ||||
-rw-r--r-- | src/kv.h | 2 | ||||
-rw-r--r-- | src/os-unix.h | 66 | ||||
-rw-r--r-- | src/os-win32.h | 100 | ||||
-rw-r--r-- | src/os.c | 56 | ||||
-rw-r--r-- | src/os.h | 110 | ||||
-rw-r--r-- | test/hook.test.c | 1 |
10 files changed, 188 insertions, 163 deletions
@@ -35,14 +35,13 @@ src="\ gameinfo.c \ hook.c \ kv.c \ - os.c \ sst.c \ udis86.c" clang -O2 -fuse-ld=lld $warnings -D_FILE_OFFSET_BITS=64 -o .build/codegen \ - src/build/codegen.c src/build/cmeta.c src/os.c + src/build/codegen.c src/build/cmeta.c clang -O2 -fuse-ld=lld $warnings -D_FILE_OFFSET_BITS=64 -o .build/mkgamedata \ - src/build/mkgamedata.c src/kv.c src/os.c + src/build/mkgamedata.c src/kv.c .build/codegen `for s in $src; do echo "src/$s"; done` .build/mkgamedata gamedata/gamelib.kv gamedata/engine.kv for s in $src; do cc "$s" done diff --git a/compile.bat b/compile.bat index 844ce01..60b4973 100644 --- a/compile.bat +++ b/compile.bat @@ -21,11 +21,11 @@ goto :eof :main
clang -municode -O2 -fuse-ld=lld %warnings% -D_CRT_SECURE_NO_WARNINGS -ladvapi32 ^
--o .build/codegen.exe src/build/codegen.c src/build/cmeta.c src/os.c || exit /b
+-o .build/codegen.exe src/build/codegen.c src/build/cmeta.c || exit /b
clang -municode -O2 -fuse-ld=lld %warnings% -D_CRT_SECURE_NO_WARNINGS -ladvapi32 ^
--o .build/mkgamedata.exe src/build/mkgamedata.c src/kv.c src/os.c || exit /b
+-o .build/mkgamedata.exe src/build/mkgamedata.c src/kv.c || exit /b
.build\codegen.exe src/autojump.c src/con_.c src/demorec.c src/dbg.c src/fixes.c ^
-src/gamedata.c src/gameinfo.c src/hook.c src/kv.c src/os.c src/sst.c src/udis86.c || exit /b
+src/gamedata.c src/gameinfo.c src/hook.c src/kv.c src/sst.c src/udis86.c || exit /b
.build\mkgamedata.exe gamedata/engine.kv gamedata/gamelib.kv || exit /b
:: llvm-rc doesn't preprocess, looks like it might later:
:: https://reviews.llvm.org/D100755?id=339141
@@ -45,7 +45,6 @@ call :cc src/gamedata.c || exit /b call :cc src/gameinfo.c || exit /b
call :cc src/hook.c || exit /b
call :cc src/kv.c || exit /b
-call :cc src/os.c || exit /b
call :cc src/sst.c || exit /b
call :cc src/udis86.c || exit /b
clang -m32 -shared -O2 -flto -fuse-ld=lld -Wl,/implib:.build/sst.lib,/Brepro ^
diff --git a/src/build/mkgamedata.c b/src/build/mkgamedata.c index 87de07d..bd7b2d5 100644 --- a/src/build/mkgamedata.c +++ b/src/build/mkgamedata.c @@ -20,8 +20,8 @@ #include "../intdefs.h" #include "../kv.h" +#include "../noreturn.h" #include "../os.h" -#include "../noreturn.h" // must come after os.h due to __declspec(noreturn) #ifdef _WIN32 #define fS "S" diff --git a/src/demorec.c b/src/demorec.c index dda692f..76e7f00 100644 --- a/src/demorec.c +++ b/src/demorec.c @@ -31,7 +31,7 @@ #include "vcall.h" #define SIGNONSTATE_SPAWN 5 // ready to receive entity packets -#define SIGNONSTATE_FULL 6 // fully connected, first non-delta packet receieved +#define SIGNONSTATE_FULL 6 // fully connected, first non-delta packet received typedef void (*VCALLCONV f_StopRecording)(void *); typedef void (*VCALLCONV f_SetSignonState)(void *, int); @@ -49,7 +49,7 @@ struct kv_parser { #define KV_PARSER_ERROR -1 /* - * These are the tokens that can be receieved by a kv_parser_cb (below). + * These are the tokens that can be received by a kv_parser_cb (below). * The x-macro and string descriptions are given to allow for easy debug * stringification. Note that this "parser" is really just lexing out these * tokens - handling the actual structure of the file should be done in the diff --git a/src/os-unix.h b/src/os-unix.h new file mode 100644 index 0000000..4ca0d4a --- /dev/null +++ b/src/os-unix.h @@ -0,0 +1,66 @@ +/* + * Copyright © 2021 Michael Smith <mikesmiffy128@gmail.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* Unix-specific definitions for os.h - don't include this directly! */ + +#ifdef __GNUC__ +#define EXPORT __attribute__((visibility("default"))) +#else +#define EXPORT int novis[-!!"visibility attribute requires Clang or GCC"]; +#endif +#define IMPORT + +typedef char os_char; +#define OS_LIT(x) x +#define os_snprintf snprintf +#define os_strchr strchr +#define os_strcmp strcmp +#define os_strcpy strcpy +#define os_strlen strlen +#define os_fopen fopen +#define os_open open +#define os_access access +#define os_stat stat +#define os_getenv getenv + +#define OS_DLSUFFIX ".so" + +#define OS_MAIN main + +#define os_dlsym dlsym + +// unix mprot flags are much nicer but cannot be defined in terms of the windows +// ones, so we use the windows ones and define them in terms of the unix ones. +// another victory for stupid! +#define PAGE_NOACCESS 0 +#define PAGE_READONLY PROT_READ +#define PAGE_READWRITE PROT_READ | PROT_WRITE +#define PAGE_EXECUTE_READ PROT_READ | PROT_EXEC +#define PAGE_EXECUTE_READWRITE PROT_READ | PROT_WRITE | PROT_EXEC + +static inline bool os_mprot(void *addr, int len, int fl) { + // round down address and round up size + addr = (void *)((unsigned long)addr & ~(4095)); + len = len + 4095 & ~(4095); + return mprotect(addr, len, fl) != -1; +} + +static inline void os_randombytes(void *buf, int sz) { + // if this call fails, the system is doomed, so loop until success and pray. + while (getentropy(buf, sz) == -1); +} + +// vi: sw=4 ts=4 noet tw=80 cc=80 diff --git a/src/os-win32.h b/src/os-win32.h new file mode 100644 index 0000000..51d2dc2 --- /dev/null +++ b/src/os-win32.h @@ -0,0 +1,100 @@ +/* + * Copyright © 2021 Michael Smith <mikesmiffy128@gmail.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* Windows-specific definitions for os.h - don't include this directly! */ + +#define IMPORT __declspec(dllimport) // only needed for variables +#define EXPORT __declspec(dllexport) + +typedef unsigned short os_char; +#define _OS_CAT(L, x) L##x +#define OS_LIT(x) _OS_CAT(L, x) + +#define os_snprintf _snwprintf +#define os_strchr wcschr +#define os_strcmp wcscmp +#define os_strcpy wcscpy +#define os_strlen wcslen +#define strncasecmp _strnicmp // stupid! + +#define os_fopen _wfopen +// yuck :( +#define _os_open3(path, flags, mode) _wopen((path), (flags) | _O_BINARY, (mode)) +#define _os_open2(path, flags) _wopen((path), (flags) | _O_BINARY) +#define _os_open(a, b, c, x, ...) x +#define os_open(...) _os_open(__VA_ARGS__, _os_open3, _os_open2, _)(__VA_ARGS__) +#define os_access _waccess +// ucrt defines __stat64 to _stat64. we want _wstat64 to be the actual function +#define _stat64(path, buf) _wstat64(path, buf) +#define os_stat _stat64 +#define os_getenv _wgetenv + +#define OS_DLSUFFIX ".dll" + +#define OS_MAIN wmain + +static inline void *os_dlsym(void *m, const char *s) { + return (void *)GetProcAddress(m, s); +} + +static inline bool os_mprot(void *addr, int len, int fl) { + unsigned long old; + return !!VirtualProtect(addr, len, fl, &old); +} + +// SystemFunction036 is the *real* name of "RtlGenRandom," and is also +// incorrectly defined in system headers. Yay. +int __stdcall SystemFunction036(void *buf, unsigned long sz); + +static inline void os_randombytes(void *buf, int sz) { + // if this call fails, the system is doomed, so loop until success and pray. + while (!SystemFunction036(buf, sz)); +} + +/* Further Windows-specific workarounds because Windows is great */ + +#ifndef PATH_MAX +// XXX: win32/crt has this dumb 260 limit even though the actual kernel imposes +// no limit (though apparently NTFS has a limit of 65535). Theoerically we could +// do some memes with UNC paths to extend it to at least have parity with Unix +// PATH_MAX (4096), but for now we just kind of accept that Windows is a +// disaster. +#define PATH_MAX MAX_PATH +#endif + +// why does Windows prefix so many things with underscores? +#define alloca _alloca +#define read _read +#define write _write +#define close _close +#define O_RDONLY _O_RDONLY +#define O_RDWR _O_RDWR +#define O_CLOEXEC _O_NOINHERIT // and why did they rename this!? +#define O_CREAT _O_CREAT +#define O_EXCL _O_EXCL +// missing access() flags +#define F_OK 0 +#define R_OK 4 +#define W_OK 2 +#define X_OK R_OK // there's no actual X bit, just pretend + +// just dump this boilerplate here as well, I spose +#define OS_WINDOWS_ERROR(arrayname) \ + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), \ + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), arrayname, \ + sizeof(arrayname), 0) + +// vi: sw=4 ts=4 noet tw=80 cc=80 diff --git a/src/os.c b/src/os.c deleted file mode 100644 index 96e3c48..0000000 --- a/src/os.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright © 2021 Michael Smith <mikesmiffy128@gmail.com> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include <stdbool.h> - -#include "intdefs.h" -#include "os.h" - -#ifdef _WIN32 -// SystemFunction036 is the *real* name of "RtlGenRandom," and is also -// incorrectly defined in system headers. Yay, Windows. -int __stdcall SystemFunction036(void *buf, ulong sz); -#endif - -bool os_mprot(void *addr, int len, int fl) { -#ifdef _WIN32 - ulong old; - return !!VirtualProtect(addr, len, fl, &old); -#else - // round down address and round up size - addr = (void *)((ulong)addr & ~(4095)); - len = len + 4095 & ~(4095); - return mprotect(addr, len, fl) != -1; -#endif -} - -#ifdef _WIN32 -void *os_dlsym(void *m, const char *s) { - return (void *)GetProcAddress(m, s); -} -#endif - -void os_randombytes(void *buf, int sz) { - // if these calls ever fail, the system is fundamentally broken with no - // recourse, so just loop until success. hopefully nothing will go wrong. -#ifdef _WIN32 - while (!SystemFunction036(buf, sz)); -#else - while (getentropy(buf, sz) == -1); -#endif -} - -// vi: sw=4 ts=4 noet tw=80 cc=80 @@ -23,8 +23,6 @@ * Here we declare an absolute ton of wrappers, macros, compatibility shims, * reimplementations and so on to try in vain to sweep the inconsistencies * between Windows and not-Windows under the rug. - * - * If this file gets any bigger it might need to be split up a bit... */ #include <fcntl.h> @@ -33,112 +31,32 @@ #define WIN32_LEAN_AND_MEAN #include <io.h> #include <wchar.h> +// DUMB HACK: noreturn.h is alphabetically before os.h so including it after +// looks weird and inconsistent. including it before breaks Windows.h though +// because of __declspec(noreturn). Undef for now, and restore at the end of +// this header. +#undef noreturn #include <Windows.h> +#include <winternl.h> #else #include <dlfcn.h> #include <limits.h> +#include <string.h> +#include <strings.h> #include <sys/mman.h> #include <unistd.h> #endif -#include "intdefs.h" - +// Things were getting unwieldy so they're now split into these headers... #ifdef _WIN32 - -#define IMPORT __declspec(dllimport) // only needed for variables -#define EXPORT __declspec(dllexport) -void *os_dlsym(void *mod, const char *sym); -#define os_char ushort -#define _OS_CAT(L, x) L##x -#define OS_LIT(x) _OS_CAT(L, x) -#define os_snprintf _snwprintf -#define os_strchr wcschr -#define os_strcmp wcscmp -#define os_strcpy wcscpy -#define os_strlen wcslen -#define strncasecmp _strnicmp // stupid! -#define OS_DLSUFFIX ".dll" -#ifndef PATH_MAX -// XXX win32/crt has this dumb 260 limit even though the actual kernel imposes -// no limit (though apparently NTFS has a limit of 65535). Theoerically we could -// do some memes with UNC paths to extend it to at least have parity with Unix -// PATH_MAX (4096), but for now we just kind of accept that Windows is a -// disaster. -#define PATH_MAX MAX_PATH +#include "os-win32.h" +// DUMB HACK part 2: restore what the #including source file had asked for +#ifdef INC_NORETURN_H +#define noreturn _Noreturn void #endif -#define os_fopen _wfopen -// yuck :( -#define _os_open3(path, flags, mode) _wopen((path), (flags) | _O_BINARY, (mode)) -#define _os_open2(path, flags) _wopen((path), (flags) | _O_BINARY) -#define _os_open(a, b, c, x, ...) x -#define os_open(...) _os_open(__VA_ARGS__, _os_open3, _os_open2, _)(__VA_ARGS__) -#define os_access _waccess -#define os_stat _stat64 -// ucrt defines __stat64 to _stat64. we want _wstat64 to be the actual function -#define _stat64(path, buf) _wstat64(path, buf) -// why exactly _does_ windows prefix so many things with underscores? -#define read _read -#define write _write -#define close _close -#define O_RDONLY _O_RDONLY -#define O_RDWR _O_RDWR -#define O_CLOEXEC _O_NOINHERIT -#define O_CREAT _O_CREAT -#define O_EXCL _O_EXCL -#define F_OK 0 -#define R_OK 4 -#define W_OK 2 -#define X_OK R_OK // there's no actual X bit -#define alloca _alloca -#define os_getenv _wgetenv -#define OS_MAIN wmain -// just dump this boilerplate here as well, I spose -#define OS_WINDOWS_ERROR(arrayname) \ - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), \ - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), arrayname, \ - sizeof(arrayname), 0) - -#else - -#ifdef __GNUC__ -#define EXPORT __attribute__((visibility("default"))) #else -#define EXPORT int novis[-!!"visibility attribute requires Clang or GCC"]; +#include "os-unix.h" #endif -#define IMPORT -#define os_dlsym dlsym -#define os_char char -#define OS_LIT(x) x -#define os_snprintf snprintf -#define os_strchr strchr -#define os_strcmp strcmp -#define os_strcpy strcpy -#define os_strlen strlen -#define OS_DLSUFFIX ".so" -#define os_fopen fopen -#define os_open open -#define os_access access -#define os_stat stat -// unix mprot flags are much nicer but cannot be defined in terms of the windows -// ones, so we use the windows ones and define them in terms of the unix ones. -// another victory for stupid! -#define PAGE_NOACCESS 0 -#define PAGE_READONLY PROT_READ -#define PAGE_READWRITE PROT_READ | PROT_WRITE -#define PAGE_EXECUTE_READ PROT_READ | PROT_EXEC -#define PAGE_EXECUTE_READWRITE PROT_READ | PROT_WRITE | PROT_EXEC -#define os_getenv getenv -#define OS_MAIN main - -#endif - -bool os_mprot(void *addr, int len, int fl); -/* - * NOTE: this should be called with a reasonably small buffer (e.g., the size of - * a private key). The maximum size of the buffer on Linux is 256, on Windows - * it's God Knows What. - */ -void os_randombytes(void *buf, int len); #endif diff --git a/test/hook.test.c b/test/hook.test.c index a918e22..831fbf6 100644 --- a/test/hook.test.c +++ b/test/hook.test.c @@ -5,7 +5,6 @@ #ifdef _WIN32 #include "../src/udis86.c" -#include "../src/os.c" #include "../src/hook.c" #include <stdarg.h> |