aboutsummaryrefslogtreecommitdiff
path: root/darwin-bootstrap/bundle-loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'darwin-bootstrap/bundle-loader.c')
-rw-r--r--darwin-bootstrap/bundle-loader.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/darwin-bootstrap/bundle-loader.c b/darwin-bootstrap/bundle-loader.c
index 7a90414..3b29b55 100644
--- a/darwin-bootstrap/bundle-loader.c
+++ b/darwin-bootstrap/bundle-loader.c
@@ -3,10 +3,12 @@
#include "ib-log.h"
#include "darwin/mach-decls.h"
#include "darwin/xxpc.h"
+#include "substitute-internal.h"
#include <dlfcn.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <mach/mig.h>
+#include <mach-o/loader.h>
#include <objc/runtime.h>
#include <CoreFoundation/CoreFoundation.h>
#include <syslog.h>
@@ -146,12 +148,60 @@ do_load:;
return true;
}
+static void notify_added_removed(const struct mach_header *mh32, bool is_add) {
+ char id_dylib_buf[32];
+ const char *id_dylib;
+
+ const mach_header_x *mh = (void *) mh32;
+ uint32_t ncmds = mh->ncmds;
+ const struct load_command *lc = (void *) (mh + 1);
+ for (uint32_t i = 0; i < ncmds; i++) {
+ if (lc->cmd == LC_ID_DYLIB) {
+ const struct dylib_command *dc = (void *) lc;
+ id_dylib = (const char *) dc + dc->dylib.name.offset;
+ goto ok;
+ }
+ lc = (void *) lc + lc->cmdsize;
+ }
+ /* no name? */
+ sprintf(id_dylib_buf, "unknown.%p", mh32);
+ id_dylib = id_dylib_buf;
+
+ok:;
+ xxpc_object_t message = xxpc_dictionary_create(NULL, NULL, 0);
+ xxpc_dictionary_set_string(message, "type", "add-remove");
+ xxpc_dictionary_set_bool(message, "is-add", is_add);
+ xxpc_dictionary_set_string(message, "id-dylib", id_dylib);
+ xxpc_connection_send_message(substituted_conn, message);
+ xxpc_release(message);
+}
+
+static void add_image_cb(const struct mach_header *mh, intptr_t vmaddr_slide) {
+ notify_added_removed(mh, true);
+
+}
+
+static void remove_image_cb(const struct mach_header *mh, intptr_t vmaddr_slide) {
+ notify_added_removed(mh, false);
+}
+
static bool handle_hello_reply(xxpc_object_t dict) {
if (IB_VERBOSE) {
char *desc = xxpc_copy_description(dict);
ib_log("hello_reply: %s", desc);
free(desc);
}
+ bool notify = xxpc_dictionary_get_bool(dict, "notify-me-of-add-remove");
+ if (notify) {
+ _dyld_register_func_for_add_image(add_image_cb);
+ _dyld_register_func_for_remove_image(remove_image_cb);
+
+ for (uint32_t i = 0, count = _dyld_image_count(); i < count; i++) {
+ const struct mach_header *mh32 = _dyld_get_image_header(i);
+ if (mh32)
+ notify_added_removed(mh32, true);
+ }
+ }
xxpc_object_t bundles = xxpc_dictionary_get_value(dict, "bundles");
if (!bundles || xxpc_get_type(bundles) != XXPC_TYPE_ARRAY)
return false;