|
|
|
|
@@ -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;
|
|
|
|
|
GHashTableIter it;
|
|
|
|
|
g_hash_table_iter_init (&it, images);
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
gpointer val;
|
|
|
|
|
|
|
|
|
|
/* Some dynlibs do not have data sections on osx (#533893) */
|
|
|
|
|
if (sec == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_slist_reverse (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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|