Align libgc vcxproj with makefile.
[mono.git] / mono / metadata / w32process-unix-osx.c
1 /**
2  * \file
3  */
4
5 #include "w32process.h"
6 #include "w32process-unix-internals.h"
7
8 #ifdef USE_OSX_BACKEND
9
10 #include <errno.h>
11 #include <unistd.h>
12 #include <sys/time.h>
13 #include <sys/proc.h>
14 #include <sys/sysctl.h>
15 #include <sys/utsname.h>
16 #include <mach-o/dyld.h>
17 #include <mach-o/getsect.h>
18
19 /* sys/resource.h (for rusage) is required when using osx 10.3 (but not 10.4) */
20 #ifdef __APPLE__
21 #include <TargetConditionals.h>
22 #include <sys/resource.h>
23 #ifdef HAVE_LIBPROC_H
24 /* proc_name */
25 #include <libproc.h>
26 #endif
27 #endif
28
29 #include "utils/mono-logger-internals.h"
30
31 gchar*
32 mono_w32process_get_name (pid_t pid)
33 {
34         gchar *ret = NULL;
35
36 #if defined (__mono_ppc__) || !defined (TARGET_OSX)
37         size_t size;
38         struct kinfo_proc *pi;
39         gint mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
40
41         if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
42                 return(ret);
43
44         if ((pi = g_malloc (size)) == NULL)
45                 return(ret);
46
47         if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
48                 if (errno == ENOMEM) {
49                         g_free (pi);
50                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
51                 }
52                 return(ret);
53         }
54
55         if (strlen (pi->kp_proc.p_comm) > 0)
56                 ret = g_strdup (pi->kp_proc.p_comm);
57
58         g_free (pi);
59 #else
60         gchar buf[256];
61         gint res;
62
63         /* No proc name on OSX < 10.5 nor ppc nor iOS */
64         memset (buf, '\0', sizeof(buf));
65         res = proc_name (pid, buf, sizeof(buf));
66         if (res == 0) {
67                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: proc_name failed, error (%d) \"%s\"", __func__, errno, g_strerror (errno));
68                 return NULL;
69         }
70
71         // Fixes proc_name triming values to 15 characters #32539
72         if (strlen (buf) >= MAXCOMLEN - 1) {
73                 gchar path_buf [PROC_PIDPATHINFO_MAXSIZE];
74                 gchar *name_buf;
75                 gint path_len;
76
77                 memset (path_buf, '\0', sizeof(path_buf));
78                 path_len = proc_pidpath (pid, path_buf, sizeof(path_buf));
79
80                 if (path_len > 0 && path_len < sizeof(path_buf)) {
81                         name_buf = path_buf + path_len;
82                         for(;name_buf > path_buf; name_buf--) {
83                                 if (name_buf [0] == '/') {
84                                         name_buf++;
85                                         break;
86                                 }
87                         }
88
89                         if (memcmp (buf, name_buf, MAXCOMLEN - 1) == 0)
90                                 ret = g_strdup (name_buf);
91                 }
92         }
93
94         if (ret == NULL && strlen (buf) > 0)
95                 ret = g_strdup (buf);
96 #endif
97
98         return ret;
99 }
100
101 gchar*
102 mono_w32process_get_path (pid_t pid)
103 {
104 #if defined(__mono_ppc__) || !defined(TARGET_OSX)
105         return mono_w32process_get_name (pid);
106 #else
107         gchar buf [PROC_PIDPATHINFO_MAXSIZE];
108         gint res;
109
110         res = proc_pidpath (pid, buf, sizeof (buf));
111         if (res <= 0)
112                 return NULL;
113         if (buf [0] == '\0')
114                 return NULL;
115         return g_strdup (buf);
116 #endif
117 }
118
119 GSList*
120 mono_w32process_get_modules (pid_t pid)
121 {
122         GSList *ret = NULL;
123         MonoW32ProcessModule *mod;
124         guint32 count;
125         int i = 0;
126
127         if (pid != getpid ())
128                 return NULL;
129
130         count = _dyld_image_count ();
131         for (i = 0; i < count; i++) {
132 #if SIZEOF_VOID_P == 8
133                 const struct mach_header_64 *hdr;
134                 const struct section_64 *sec;
135 #else
136                 const struct mach_header *hdr;
137                 const struct section *sec;
138 #endif
139                 const char *name;
140
141                 name = _dyld_get_image_name (i);
142 #if SIZEOF_VOID_P == 8
143                 hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
144                 sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
145 #else
146                 hdr = _dyld_get_image_header (i);
147                 sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
148 #endif
149
150                 /* Some dynlibs do not have data sections on osx (#533893) */
151                 if (sec == 0)
152                         continue;
153
154                 mod = g_new0 (MonoW32ProcessModule, 1);
155                 mod->address_start = GINT_TO_POINTER (sec->addr);
156                 mod->address_end = GINT_TO_POINTER (sec->addr+sec->size);
157                 mod->perms = g_strdup ("r--p");
158                 mod->address_offset = 0;
159                 mod->device = makedev (0, 0);
160                 mod->inode = i;
161                 mod->filename = g_strdup (name);
162
163                 if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
164                         ret = g_slist_prepend (ret, mod);
165                 } else {
166                         mono_w32process_module_free (mod);
167                 }
168         }
169
170         return g_slist_reverse (ret);
171 }
172
173 #endif