aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDudi <dudicon@gmail.com>2021-11-11 13:27:23 +0200
committerDudi <dudicon@gmail.com>2021-11-11 13:27:23 +0200
commitc5aa6ac920f0bfeacb9b3d685ec5d4117e3517f1 (patch)
treeb96354b866ffb0024b76296ecc950055b5d23cb2
parent284047b761bd61e3c0518b0be235aa77172b1010 (diff)
downloadsubhook-c5aa6ac920f0bfeacb9b3d685ec5d4117e3517f1.zip
subhook-c5aa6ac920f0bfeacb9b3d685ec5d4117e3517f1.tar.gz
subhook-c5aa6ac920f0bfeacb9b3d685ec5d4117e3517f1.tar.bz2
Add MacOS support
-rw-r--r--CMakeLists.txt2
-rw-r--r--README.md6
-rw-r--r--subhook.c2
-rw-r--r--subhook.h8
-rw-r--r--subhook_macos.c75
-rw-r--r--tests/test.c2
-rw-r--r--tests/test.cpp2
7 files changed, 88 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 84999c4..afc4c11 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,6 +37,8 @@ set(SUBHOOK_HEADERS subhook.h)
set(SUBHOOK_SOURCES subhook.c subhook_private.h subhook_x86.c)
if(WIN32)
list(APPEND SUBHOOK_SOURCES subhook_windows.c)
+elseif(APPLE)
+ list(APPEND SUBHOOK_SOURCES subhook_macos.c)
elseif(UNIX)
list(APPEND SUBHOOK_SOURCES subhook_unix.c)
endif()
diff --git a/README.md b/README.md
index ff51c9c..01c905a 100644
--- a/README.md
+++ b/README.md
@@ -152,10 +152,8 @@ Known issues
memory as executable, which prevents the use of trampolines.
For example, on Fedora you can have such problems because of SELinux (though
- you can disable it or exclude your files). On macOS Catalina the
- `mprotect()` call inside `subhook_new` will fail with "Permission denied"
- (see https://github.com/Zeex/subhook/issues/45).
-
+ you can disable it or exclude your files).
+
License
-------
diff --git a/subhook.c b/subhook.c
index 8ea7d51..1c96888 100644
--- a/subhook.c
+++ b/subhook.c
@@ -68,6 +68,8 @@ SUBHOOK_EXPORT void SUBHOOK_API subhook_set_disasm_handler(
#include "subhook_windows.c"
#elif defined SUBHOOK_UNIX
#include "subhook_unix.c"
+#elif defined SUBHOOK_APPLE
+ #include "subhook_macos.c"
#endif
#if defined SUBHOOK_X86 || defined SUBHOOK_X86_64
diff --git a/subhook.h b/subhook.h
index d2f6814..d8216c6 100644
--- a/subhook.h
+++ b/subhook.h
@@ -41,9 +41,11 @@
#if defined _WIN32 || defined __CYGWIN__
#define SUBHOOK_WINDOWS
-#elif defined __linux__ || defined __APPLE__ \
+#elif defined __linux__ \
|| defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
#define SUBHOOK_UNIX
+ #elif defined __APPLE__
+ #define SUBHOOK_APPLE
#else
#error Unsupported operating system
#endif
@@ -65,7 +67,7 @@
#if defined SUBHOOK_X86
#if defined SUBHOOK_WINDOWS
#define SUBHOOK_API __cdecl
- #elif defined SUBHOOK_UNIX
+ #elif defined SUBHOOK_UNIX || defined SUBHOOK_APPLE
#define SUBHOOK_API __attribute__((cdecl))
#endif
#else
@@ -80,7 +82,7 @@
#else
#define SUBHOOK_EXPORT SUBHOOK_EXTERN __declspec(dllimport)
#endif
- #elif defined SUBHOOK_UNIX
+ #elif defined SUBHOOK_UNIX || defined SUBHOOK_APPLE
#if defined SUBHOOK_IMPLEMENTATION
#define SUBHOOK_EXPORT SUBHOOK_EXTERN __attribute__((visibility("default")))
#else
diff --git a/subhook_macos.c b/subhook_macos.c
new file mode 100644
index 0000000..866edf5
--- /dev/null
+++ b/subhook_macos.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012-2018 Zeex
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <mach/mach.h>
+
+#define SUBHOOK_CODE_PROTECT_FLAGS (PROT_READ | PROT_WRITE | PROT_EXEC)
+
+int subhook_unprotect(void *address, size_t size) {
+ long pagesize;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+ address = (void *)((long)address & ~(pagesize - 1));
+ int error = mprotect(address, size, SUBHOOK_CODE_PROTECT_FLAGS);
+
+ if (-1 == error)
+ {
+ // If mprotect fails, try to use VM_PROT_COPY with vm_protect
+ kern_return_t kret = vm_protect(mach_task_self(), (unsigned long)address, size, 0, SUBHOOK_CODE_PROTECT_FLAGS | VM_PROT_COPY);
+ if (kret != KERN_SUCCESS)
+ {
+ error = -1;
+ }
+ error = 0;
+ }
+
+ return error;
+}
+
+void *subhook_alloc_code(size_t size) {
+ void *address;
+
+ address = mmap(NULL,
+ size,
+ SUBHOOK_CODE_PROTECT_FLAGS,
+ #if defined MAP_32BIT && !defined __APPLE__
+ MAP_32BIT |
+ #endif
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1,
+ 0);
+ return address == MAP_FAILED ? NULL : address;
+}
+
+int subhook_free_code(void *address, size_t size) {
+ if (address == NULL) {
+ return 0;
+ }
+ return munmap(address, size);
+}
diff --git a/tests/test.c b/tests/test.c
index d8b39fd..5526653 100644
--- a/tests/test.c
+++ b/tests/test.c
@@ -8,7 +8,7 @@ typedef void (*foo_func_t)(void);
#ifdef SUBHOOK_X86
#if defined SUBHOOK_WINDOWS
#define FOO_CALL __cdecl
- #elif defined SUBHOOK_UNIX
+ #elif defined SUBHOOK_UNIX || defined SUBHOOK_APPLE
#define FOO_CALL __attribute__((cdecl))
#endif
#endif
diff --git a/tests/test.cpp b/tests/test.cpp
index 7ba167a..30b7ca4 100644
--- a/tests/test.cpp
+++ b/tests/test.cpp
@@ -7,7 +7,7 @@ typedef void (*foo_func_t)();
#ifdef SUBHOOK_X86
#if defined SUBHOOK_WINDOWS
#define FOO_CALL __cdecl
- #elif defined SUBHOOK_UNIX
+ #elif defined SUBHOOK_UNIX || defined SUBHOOK_APPLE
#define FOO_CALL __attribute__((cdecl))
#endif
#endif