diff options
author | comex | 2015-01-29 01:48:09 -0500 |
---|---|---|
committer | comex | 2015-01-29 01:48:17 -0500 |
commit | 5d7d4cdf531234390055540dc4ccc478268b0588 (patch) | |
tree | 4bda0d50e2284986d730efe7ce9db77a28f51b3f | |
parent | port some old code (diff) | |
download | substitute-5d7d4cdf531234390055540dc4ccc478268b0588.tar.gz |
get rid of the unnecessary CoreFoundation dependency
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | lib/cbit/htab.h | 19 | ||||
-rw-r--r-- | lib/darwin/stop-other-threads.c | 82 | ||||
-rw-r--r-- | test/test-htab.c | 17 | ||||
-rw-r--r-- | test/test-stop-threads.c | 15 |
5 files changed, 85 insertions, 54 deletions
@@ -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)); |