Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mono/metadata/w32process-unix-bsd.c5
-rw-r--r--mono/metadata/w32process-unix-default.c5
-rw-r--r--mono/metadata/w32process-unix-haiku.c5
-rw-r--r--mono/metadata/w32process-unix-internals.h3
-rw-r--r--mono/metadata/w32process-unix-osx.c153
-rw-r--r--mono/metadata/w32process-unix.c4
6 files changed, 134 insertions, 41 deletions
diff --git a/mono/metadata/w32process-unix-bsd.c b/mono/metadata/w32process-unix-bsd.c
index d09bc9f506e..e368c19bd8b 100644
--- a/mono/metadata/w32process-unix-bsd.c
+++ b/mono/metadata/w32process-unix-bsd.c
@@ -175,6 +175,11 @@ mono_w32process_get_modules (pid_t pid)
return g_slist_reverse (ret);
}
+void
+mono_w32process_platform_init_once (void)
+{
+}
+
#else
MONO_EMPTY_SOURCE_FILE (w32process_unix_bsd);
diff --git a/mono/metadata/w32process-unix-default.c b/mono/metadata/w32process-unix-default.c
index e2fda17fb5a..0f148aec286 100644
--- a/mono/metadata/w32process-unix-default.c
+++ b/mono/metadata/w32process-unix-default.c
@@ -360,4 +360,9 @@ mono_w32process_get_modules (pid_t pid)
#endif
}
+void
+mono_w32process_platform_init_once (void)
+{
+}
+
#endif
diff --git a/mono/metadata/w32process-unix-haiku.c b/mono/metadata/w32process-unix-haiku.c
index 0b3c82436c7..dbd312c8d86 100644
--- a/mono/metadata/w32process-unix-haiku.c
+++ b/mono/metadata/w32process-unix-haiku.c
@@ -57,6 +57,11 @@ mono_w32process_get_modules (pid_t pid)
return g_slist_reverse (ret);
}
+void
+mono_w32process_platform_init_once (void)
+{
+}
+
#else
MONO_EMPTY_SOURCE_FILE (w32process_unix_haiku);
diff --git a/mono/metadata/w32process-unix-internals.h b/mono/metadata/w32process-unix-internals.h
index 7ba5f7e002e..056177dd22a 100644
--- a/mono/metadata/w32process-unix-internals.h
+++ b/mono/metadata/w32process-unix-internals.h
@@ -40,6 +40,9 @@ mono_w32process_get_name (pid_t pid);
GSList*
mono_w32process_get_modules (pid_t pid);
+void
+mono_w32process_platform_init_once (void);
+
static void G_GNUC_UNUSED
mono_w32process_module_free (MonoW32ProcessModule *module)
{
diff --git a/mono/metadata/w32process-unix-osx.c b/mono/metadata/w32process-unix-osx.c
index c687f6a70a1..2568a44223e 100644
--- a/mono/metadata/w32process-unix-osx.c
+++ b/mono/metadata/w32process-unix-osx.c
@@ -15,6 +15,7 @@
#include <sys/utsname.h>
#include <mach-o/dyld.h>
#include <mach-o/getsect.h>
+#include <dlfcn.h>
/* sys/resource.h (for rusage) is required when using osx 10.3 (but not 10.4) */
#ifdef __APPLE__
@@ -117,58 +118,128 @@ mono_w32process_get_path (pid_t pid)
#endif
}
-GSList*
+struct mono_dyld_image_info
+{
+ const void *header_addr;
+ const void *data_section_start;
+ const void *data_section_end;
+ const char *name;
+ guint64 order;
+};
+
+static guint64 dyld_order = 0;
+static GHashTable *images;
+static mono_mutex_t images_mutex;
+
+static int
+sort_modules_by_load_order (gconstpointer a, gconstpointer b)
+{
+ MonoW32ProcessModule *ma = (MonoW32ProcessModule *) a;
+ MonoW32ProcessModule *mb = (MonoW32ProcessModule *) b;
+ return ma->inode == mb->inode ? 0 : ma->inode < mb->inode ? -1 : 1;
+}
+
+GSList *
mono_w32process_get_modules (pid_t pid)
{
GSList *ret = NULL;
- MonoW32ProcessModule *mod;
- guint32 count;
- int i = 0;
-
+ MONO_ENTER_GC_SAFE;
if (pid != getpid ())
- return NULL;
+ goto done;
- count = _dyld_image_count ();
- for (i = 0; i < count; i++) {
-#if SIZEOF_VOID_P == 8
- const struct mach_header_64 *hdr;
- const struct section_64 *sec;
-#else
- const struct mach_header *hdr;
- const struct section *sec;
-#endif
- const char *name;
-
- name = _dyld_get_image_name (i);
-#if SIZEOF_VOID_P == 8
- hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
- sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
-#else
- hdr = _dyld_get_image_header (i);
- sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
-#endif
+ GHashTableIter it;
+ g_hash_table_iter_init (&it, images);
- /* Some dynlibs do not have data sections on osx (#533893) */
- if (sec == 0)
- continue;
+ gpointer val;
- mod = g_new0 (MonoW32ProcessModule, 1);
- mod->address_start = GINT_TO_POINTER (sec->addr);
- mod->address_end = GINT_TO_POINTER (sec->addr+sec->size);
+ mono_os_mutex_lock (&images_mutex);
+ while (g_hash_table_iter_next (&it, NULL, &val)) {
+ struct mono_dyld_image_info *info = (struct mono_dyld_image_info *) val;
+ MonoW32ProcessModule *mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->address_start = GINT_TO_POINTER (info->data_section_start);
+ mod->address_end = GINT_TO_POINTER (info->data_section_end);
mod->perms = g_strdup ("r--p");
mod->address_offset = 0;
- mod->device = makedev (0, 0);
- mod->inode = i;
- mod->filename = g_strdup (name);
-
- if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- mono_w32process_module_free (mod);
- }
+ mod->device = 0;
+ mod->inode = info->order;
+ mod->filename = g_strdup (info->name);
+ ret = g_slist_prepend (ret, mod);
}
+ mono_os_mutex_unlock (&images_mutex);
+ ret = g_slist_sort (ret, &sort_modules_by_load_order);
+done:
+ MONO_EXIT_GC_SAFE;
+ return ret;
+}
+
+static void
+mono_dyld_image_info_free (void *info)
+{
+ struct mono_dyld_image_info *dinfo = (struct mono_dyld_image_info *) info;
+ g_free ((void *) dinfo->name);
+ g_free (dinfo);
+}
+
+static void
+image_added (const struct mach_header *hdr32, intptr_t vmaddr_slide)
+{
+ #if SIZEOF_VOID_P == 8
+ const struct mach_header_64 *hdr64 = (const struct mach_header_64 *)hdr32;
+ const struct section_64 *sec = getsectbynamefromheader_64 (hdr64, SEG_DATA, SECT_DATA);
+ #else
+ const struct section *sec = getsectbynamefromheader (hdr32, SEG_DATA, SECT_DATA);
+ #endif
+ Dl_info dlinfo;
+ if (!dladdr (hdr32, &dlinfo)) return;
+ if (sec == NULL) return;
+
+ mono_os_mutex_lock (&images_mutex);
+ gpointer found = g_hash_table_lookup (images, (gpointer) hdr32);
+ mono_os_mutex_unlock (&images_mutex);
+
+ if (found == NULL) {
+ struct mono_dyld_image_info *info = g_new0 (struct mono_dyld_image_info, 1);
+ info->header_addr = hdr32;
+ info->data_section_start = GINT_TO_POINTER (sec->addr);
+ info->data_section_end = GINT_TO_POINTER (sec->addr + sec->size);
+ info->name = g_strdup (dlinfo.dli_fname);
+ info->order = dyld_order;
+ ++dyld_order;
+
+ mono_os_mutex_lock (&images_mutex);
+ g_hash_table_insert (images, (gpointer) hdr32, info);
+ mono_os_mutex_unlock (&images_mutex);
+ }
+}
+
+static void
+image_removed (const struct mach_header *hdr32, intptr_t vmaddr_slide)
+{
+ mono_os_mutex_lock (&images_mutex);
+ g_hash_table_remove (images, hdr32);
+ mono_os_mutex_unlock (&images_mutex);
+}
- return g_slist_reverse (ret);
+void
+mono_w32process_platform_init_once (void)
+{
+ mono_os_mutex_init (&images_mutex);
+ images = g_hash_table_new_full (NULL, NULL, NULL, &mono_dyld_image_info_free);
+
+ /* Ensure that the functions used within the lock-protected region in
+ * mono_w32process_get_modules have been loaded, in case these symbols
+ * are lazily bound. g_new0 and g_strdup will be called by
+ * _dyld_register_func_for_add_image when it calls image_added with the
+ * current list of all loaded dynamic libraries
+ */
+ GSList *dummy = g_slist_prepend (NULL, NULL);
+ g_slist_free (dummy);
+ GHashTableIter it;
+ g_hash_table_iter_init (&it, images);
+ g_hash_table_iter_next (&it, NULL, NULL);
+
+ _dyld_register_func_for_add_image (&image_added);
+ _dyld_register_func_for_remove_image (&image_removed);
}
#else
diff --git a/mono/metadata/w32process-unix.c b/mono/metadata/w32process-unix.c
index b4fcc3016fe..426e12810c4 100644
--- a/mono/metadata/w32process-unix.c
+++ b/mono/metadata/w32process-unix.c
@@ -85,6 +85,7 @@
#include <mono/utils/mono-io-portability.h>
#include <mono/utils/w32api.h>
#include <mono/utils/mono-errno.h>
+#include <mono/utils/mono-once.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/mono-threads-coop.h>
#include "object-internals.h"
@@ -594,6 +595,8 @@ process_set_name (MonoW32HandleProcess *process_handle)
}
}
+static mono_once_t init_state = MONO_ONCE_INIT;
+
void
mono_w32process_init (void)
{
@@ -615,6 +618,7 @@ mono_w32process_init (void)
g_assert (current_process != INVALID_HANDLE_VALUE);
mono_coop_mutex_init (&processes_mutex);
+ mono_once (&init_state, &mono_w32process_platform_init_once);
}
void