aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcomex2015-01-29 01:48:09 -0500
committercomex2015-01-29 01:48:17 -0500
commit5d7d4cdf531234390055540dc4ccc478268b0588 (patch)
tree4bda0d50e2284986d730efe7ce9db77a28f51b3f
parentport some old code (diff)
downloadsubstitute-5d7d4cdf531234390055540dc4ccc478268b0588.tar.gz
get rid of the unnecessary CoreFoundation dependency
-rw-r--r--Makefile6
-rw-r--r--lib/cbit/htab.h19
-rw-r--r--lib/darwin/stop-other-threads.c82
-rw-r--r--test/test-htab.c17
-rw-r--r--test/test-stop-threads.c15
5 files changed, 85 insertions, 54 deletions
diff --git a/Makefile b/Makefile
index 6eb3118..2d10ec8 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ CC := clang
CXX := clang++
ARCH := -arch x86_64
XCFLAGS := -O3 -Wall -Wextra -Werror -Ilib $(ARCH)
-LIB_LDFLAGS := -lobjc -framework CoreFoundation -dynamiclib -fvisibility=hidden -install_name /usr/lib/libsubstitute.0.dylib -dead_strip
+LIB_LDFLAGS := -lobjc -dynamiclib -fvisibility=hidden -install_name /usr/lib/libsubstitute.0.dylib -dead_strip
IOS_APP_LDFLAGS := -framework UIKit -framework Foundation -dead_strip
ifneq (,$(IS_IOS))
# I don't know anything in particular that would break this on older versions,
@@ -105,7 +105,7 @@ out/%.bin: out/%.o Makefile
define define_test
out/test-$(1): test/test-$(2).[cm]* $(HEADERS) $(GENERATED) Makefile out/libsubstitute.dylib
- $(3) -g -o $$@ $$< -Ilib -Isubstrate -Lout -lsubstitute
+ $(3) -g -o $$@ $$< -Ilib -Isubstrate -Lout -lsubstitute -dead_strip
install_name_tool -change /usr/lib/libsubstitute.0.dylib '@executable_path/libsubstitute.dylib' $$@
ifneq (,$(IS_IOS))
ldid -Sent.plist $$@
@@ -129,7 +129,7 @@ $(eval $(call define_test,imp-forwarding,imp-forwarding,$(CC) -std=c11 -framewor
$(eval $(call define_test,objc-hook,objc-hook,$(CC) -std=c11 -framework Foundation -lsubstitute))
$(eval $(call define_test,interpose,interpose,$(CC) -std=c11 -lsubstitute))
$(eval $(call define_test,inject,inject,$(CC) -std=c11 -lsubstitute out/darwin/inject.o out/darwin/read.o))
-$(eval $(call define_test,stop-threads,stop-threads,$(CC) -std=c11 out/darwin/stop-other-threads.o -framework CoreFoundation))
+$(eval $(call define_test,stop-threads,stop-threads,$(CC) -std=c11 out/darwin/stop-other-threads.o))
$(eval $(call define_test,execmem,execmem,$(CC) -std=c11 out/darwin/execmem.o -segprot __TEST rwx rx))
$(eval $(call define_test,hook-functions,hook-functions,$(CC) -std=c11 -lsubstitute))
$(eval $(call define_test,posixspawn-hook,posixspawn-hook,$(CC) -std=c11))
diff --git a/lib/cbit/htab.h b/lib/cbit/htab.h
index 861a9be..5c9b993 100644
--- a/lib/cbit/htab.h
+++ b/lib/cbit/htab.h
@@ -95,7 +95,6 @@ struct htab_internal {
key_ty *bucket = (void *) (buckets + i * entry_size); \
if (null_func(bucket)) { \
if (add) { \
- *bucket = *key; \
hi->length++; \
return bucket; \
} else { \
@@ -213,15 +212,25 @@ struct htab_internal {
} \
UNUSED_STATIC_INLINE \
bucket_ty *htab_setbucket_##name(htab_ty *restrict ht, \
- const key_ty *restrict key) { \
+ const key_ty *restrict key) { \
return __htab_key_lookup_##key_name(&ht->hi, key, sizeof(bucket_ty), \
true, true); \
} \
UNUSED_STATIC_INLINE \
value_ty *htab_setp_##name(const htab_ty *restrict ht, \
- const key_ty *restrict key) { \
+ const key_ty *restrict key, \
+ bool *new_p) { \
bucket_ty *bucket = htab_setbucket_##name((void *) ht, key); \
- return bucket ? &bucket->value : NULL; \
+ bool new = false; \
+ if (__htab_key_is_null_##key_name(&bucket->key)) { \
+ bucket->key = *key; \
+ new = true; \
+ } else { \
+ new = false; \
+ } \
+ if (new_p) \
+ *new_p = new; \
+ return &bucket->value; \
} \
UNUSED_STATIC_INLINE \
bool htab_remove_##name(htab_ty *restrict ht, const key_ty *restrict key) { \
@@ -240,7 +249,7 @@ struct htab_internal {
return __htab_key_resize_##key_name(&ht->hi, size, sizeof(bucket_ty)); \
} \
UNUSED_STATIC_INLINE \
- void htab_free_##name(htab_ty *ht) { \
+ void htab_free_storage_##name(htab_ty *ht) { \
if (ht->base != ht->storage) \
free(ht->base); \
}
diff --git a/lib/darwin/stop-other-threads.c b/lib/darwin/stop-other-threads.c
index ee9e803..1a4f43f 100644
--- a/lib/darwin/stop-other-threads.c
+++ b/lib/darwin/stop-other-threads.c
@@ -1,19 +1,17 @@
-#if 0
#include "substitute.h"
#include "substitute-internal.h"
#include "darwin/mach-decls.h"
+#include "stop-other-threads.h"
+#include "cbit/htab.h"
#include <pthread.h>
#include <mach/mach.h>
-static void release_port(UNUSED CFAllocatorRef allocator, const void *value) {
- mach_port_t thread = (mach_port_t) value;
- thread_resume(thread);
- mach_port_deallocate(mach_task_self(), thread);
-}
-static CFSetCallBacks suspend_port_callbacks = {
- .version = 0,
- .release = release_port,
-};
+#define port_hash(portp) (*(portp))
+#define port_eq(port1p, port2p) (*(port1p) == *(port2p))
+#define port_null(portp) (*(portp) == MACH_PORT_NULL)
+DECL_STATIC_HTAB_KEY(mach_port_t, mach_port_t, port_hash, port_eq, port_null, 0);
+struct empty {};
+DECL_HTAB(mach_port_set, mach_port_t, struct empty);
static bool apply_one_pcp(mach_port_t thread,
uintptr_t (*callback)(void *ctx, uintptr_t pc),
@@ -69,27 +67,6 @@ static bool apply_one_pcp(mach_port_t thread,
return true;
}
-int apply_pc_patch_callback(void *token,
- uintptr_t (*pc_patch_callback)(void *ctx, uintptr_t pc),
- void *ctx) {
- CFMutableSetRef suspended_set = token;
- CFIndex count = CFSetGetCount(suspended_set);
- if (!count)
- return SUBSTITUTE_OK;
- /* great API there CF */
- const void **ports = malloc(sizeof(*ports) * count);
- CFSetGetValues(suspended_set, ports);
- int ret = SUBSTITUTE_OK;
- for (CFIndex i = 0; i < count; i++) {
- if (!apply_one_pcp((mach_port_t) ports[i], pc_patch_callback, ctx)) {
- ret = SUBSTITUTE_ERR_ADJUSTING_THREADS;
- break;
- }
- }
- free(ports);
- return ret;
-}
-
int stop_other_threads(void **token_ptr) {
if (!pthread_main_np())
return SUBSTITUTE_ERR_NOT_ON_MAIN_THREAD;
@@ -101,7 +78,9 @@ int stop_other_threads(void **token_ptr) {
* created while we're looping, without suspending anything twice. Keep
* looping until only threads we already suspended before this loop are
* there. */
- CFMutableSetRef suspended_set = CFSetCreateMutable(NULL, 0, &suspend_port_callbacks);
+ HTAB_STORAGE(mach_port_set) *hs = malloc(sizeof(*hs));
+ HTAB_STORAGE_INIT(hs, mach_port_set);
+ struct htab_mach_port_set *suspended_set = &hs->h;
thread_act_array_t ports = 0;
mach_msg_type_number_t nports = 0;
@@ -118,14 +97,14 @@ int stop_other_threads(void **token_ptr) {
for (mach_msg_type_number_t i = 0; i < nports; i++) {
mach_port_t port = ports[i];
- void *casted_port = (void *) (uintptr_t) port;
+ struct htab_bucket_mach_port_set *bucket;
if (port == self ||
- CFSetContainsValue(suspended_set, casted_port)) {
+ (bucket = htab_setbucket_mach_port_set(suspended_set, &port),
+ bucket->key)) {
/* already suspended, ignore */
mach_port_deallocate(mach_task_self(), port);
} else {
got_new = true;
- printf("suspending %d (self=%d)\n", port, self);
kr = thread_suspend(port);
if (kr == KERN_TERMINATED) {
/* too late */
@@ -138,7 +117,7 @@ int stop_other_threads(void **token_ptr) {
nports * sizeof(*ports));
goto fail;
}
- CFSetAddValue(suspended_set, casted_port);
+ bucket->key = port;
}
}
vm_deallocate(mach_task_self(), (vm_address_t) ports,
@@ -150,13 +129,36 @@ int stop_other_threads(void **token_ptr) {
return SUBSTITUTE_OK;
fail:
- CFRelease(suspended_set);
+ resume_other_threads(suspended_set);
+ return ret;
+}
+
+int apply_pc_patch_callback(void *token,
+ uintptr_t (*pc_patch_callback)(void *ctx, uintptr_t pc),
+ void *ctx) {
+ struct htab_mach_port_set *suspended_set = token;
+ int ret = SUBSTITUTE_OK;
+ HTAB_FOREACH(suspended_set, mach_port_t *threadp,
+ UNUSED struct empty *_,
+ mach_port_set) {
+ if (!apply_one_pcp(*threadp, pc_patch_callback, ctx)) {
+ ret = SUBSTITUTE_ERR_ADJUSTING_THREADS;
+ break;
+ }
+ }
return ret;
}
+
int resume_other_threads(void *token) {
- CFMutableSetRef suspended_set = token;
- CFRelease(suspended_set);
+ struct htab_mach_port_set *suspended_set = token;
+ HTAB_FOREACH(suspended_set, mach_port_t *threadp,
+ UNUSED struct empty *_,
+ mach_port_set) {
+ thread_resume(*threadp);
+ mach_port_deallocate(mach_task_self(), *threadp);
+ }
+ htab_free_storage_mach_port_set(suspended_set);
+ free(suspended_set);
return SUBSTITUTE_OK; /* eh */
}
-#endif
diff --git a/test/test-htab.c b/test/test-htab.c
index 2986de8..ad23cdb 100644
--- a/test/test-htab.c
+++ b/test/test-htab.c
@@ -1,6 +1,7 @@
#include "cbit/htab.h"
#include <string.h>
#include <stdio.h>
+#include <assert.h>
struct teststr {
bool valid;
const char *what;
@@ -19,15 +20,23 @@ int main() {
for(int i = 0; i < 100; i++) {
const char *k;
asprintf((char **) &k, "foo%d", i);
- *htab_setp_teststr_int(hp, &k) = i;
+ bool new;
+ *htab_setp_teststr_int(hp, &k, &new) = i;
+ assert(new);
+ }
+ {
+ const char *k = "foo31";
+ bool new;
+ htab_setp_teststr_int(hp, &k, NULL);
+ htab_setp_teststr_int(hp, &k, &new);
+ assert(!new);
+ htab_remove_teststr_int(hp, &k);
}
- const char *to_remove = "foo31";
- htab_remove_teststr_int(hp, &to_remove);
HTAB_FOREACH(hp, const char **k, int *v, teststr_int) {
if(*v % 10 == 1)
printf("%s -> %d\n", *k, *v);
}
- htab_free_teststr_int(hp);
+ htab_free_storage_teststr_int(hp);
}
/*
diff --git a/test/test-stop-threads.c b/test/test-stop-threads.c
index 829e73e..d53d8cd 100644
--- a/test/test-stop-threads.c
+++ b/test/test-stop-threads.c
@@ -4,15 +4,22 @@
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
+/* printf without taking any locks - because they might be taken at stop time */
+#define ulprintf(...) do { \
+ char buf[256]; \
+ int len = sprintf(buf, __VA_ARGS__); \
+ write(1, buf, len); \
+} while(0)
+
static void *some_thread(void *ip) {
long i = (long) ip;
while (1) {
- printf("Hello from %ld\n", i);
+ ulprintf("Hello from %ld\n", i);
sleep(1);
}
}
static void replacement() {
- printf("Bye\n");
+ ulprintf("Bye\n");
pthread_exit(NULL);
}
static uintptr_t patch_callback(void *ctx, UNUSED uintptr_t pc) {
@@ -26,9 +33,13 @@ int main() {
pthread_create(&pts[i], NULL, some_thread, (void *) i);
sleep(1);
void *stop_token;
+ ulprintf("stopping\n");
assert(!stop_other_threads(&stop_token));
+ ulprintf("stopped\n");
assert(!apply_pc_patch_callback(stop_token, patch_callback, NULL));
+ ulprintf("resuming\n");
assert(!resume_other_threads(stop_token));
+ ulprintf("resumed\n");
void *out;
for (long i = 0; i < 10; i++)
assert(!pthread_join(pts[i], &out));