5 #include "w32process.h"
6 #include "w32process-unix-internals.h"
8 #ifdef USE_DEFAULT_BACKEND
13 /* procfs.h cannot be included if this define is set, but it seems to work fine if it is undefined */
14 #if _FILE_OFFSET_BITS == 64
15 #undef _FILE_OFFSET_BITS
17 #define _FILE_OFFSET_BITS 64
24 /* like solaris, just different */
25 #include <sys/procfs.h>
26 /* fallback for procfs-less i */
28 #include <sys/types.h>
33 #include <sys/mkdev.h>
34 #elif defined MAJOR_IN_SYSMACROS
35 #include <sys/sysmacros.h>
38 #include "utils/mono-logger-internals.h"
39 #include "icall-decl.h"
42 #define MAXPATHLEN 242
45 /* XXX: why don't we just use proclib? */
47 mono_w32process_get_name (pid_t pid
)
54 #if defined(HOST_SOLARIS) || (defined(_AIX) && !defined(__PASE__))
55 filename
= g_strdup_printf ("/proc/%d/psinfo", pid
);
56 if ((fp
= fopen (filename
, "r")) != NULL
) {
60 nread
= fread (&info
, sizeof (info
), 1, fp
);
62 ret
= g_strdup (info
.pr_fname
);
68 #elif defined(__PASE__)
69 /* AIX has a procfs, but it's not available on i */
70 struct procentry64 proc
;
74 if (getprocs64(&proc
, sizeof (proc
), NULL
, NULL
, &newpid
, 1) == 1) {
75 ret
= g_strdup (proc
.pi_comm
);
78 memset (buf
, '\0', sizeof(buf
));
79 filename
= g_strdup_printf ("/proc/%d/exe", pid
);
80 #if defined(HAVE_READLINK)
81 if (readlink (filename
, buf
, 255) > 0) {
91 filename
= g_strdup_printf ("/proc/%d/cmdline", pid
);
92 if ((fp
= fopen (filename
, "r")) != NULL
) {
93 if (fgets (buf
, 256, fp
) != NULL
) {
105 filename
= g_strdup_printf ("/proc/%d/stat", pid
);
106 if ((fp
= fopen (filename
, "r")) != NULL
) {
107 if (fgets (buf
, 256, fp
) != NULL
) {
110 start
= strchr (buf
, '(');
112 end
= strchr (start
+ 1, ')');
115 ret
= g_strndup (start
+ 1,
130 mono_w32process_get_path (pid_t pid
)
132 return mono_w32process_get_name (pid
);
136 open_process_map (int pid
, const char *mode
)
139 const gchar
*proc_path
[] = {
140 "/proc/%d/maps", /* GNU/Linux */
141 "/proc/%d/map", /* FreeBSD */
145 for (i
= 0; proc_path
[i
]; i
++) {
149 filename
= g_strdup_printf (proc_path
[i
], pid
);
150 fp
= fopen (filename
, mode
);
162 mono_w32process_get_modules (pid_t pid
)
165 /* due to procfs, this won't work on i */
168 MonoW32ProcessModule
*mod
;
173 char pidpath
[32]; /* "/proc/<uint64_t max>/map" plus null, rounded */
174 char libpath
[MAXPATHLEN
+ 1];
175 char membername
[MAXPATHLEN
+ 1];
176 char combinedname
[(MAXPATHLEN
* 2) + 3]; /* lib, member, (), and nul */
178 sprintf (pidpath
, "/proc/%d/map", pid
);
179 if ((fp
= fopen(pidpath
, "r"))) {
180 while (fread (&module
, sizeof (module
), 1, fp
) == 1
181 /* proc(4) declares such a struct to be the array terminator */
182 && (module
.pr_size
!= 0 && module
.pr_mflags
!= 0)
183 && (module
.pr_mflags
& MA_READ
)) {
185 fgetpos64 (fp
, &curpos
); /* save our position */
186 fseeko (fp
, module
.pr_pathoff
, SEEK_SET
);
187 while ((libpath
[i
++] = fgetc (fp
)));
189 while ((membername
[i
++] = fgetc (fp
)));
191 fsetpos64 (fp
, &curpos
); /* back to normal */
193 mod
= g_new0 (MonoW32ProcessModule
, 1);
194 mod
->address_start
= module
.pr_vaddr
;
195 mod
->address_end
= module
.pr_vaddr
+ module
.pr_size
;
196 mod
->address_offset
= (void*)module
.pr_off
;
197 mod
->perms
= g_strdup ("r--p"); /* XXX? */
199 /* AIX has what appears to be device, channel and inode information,
200 * but it's in a string. Try parsing it.
202 * XXX: I believe it's fstype.devno.chano.inode, but I'm uncertain
203 * as to how that maps out, so I only fill in the inode (like BSD)
205 sscanf (module
.pr_mapname
, "%*[^.].%*lu.%*u.%lu", &(mod
->inode
));
208 snprintf(combinedname
, MAXPATHLEN
, "%s(%s)", libpath
, membername
);
209 mod
->filename
= g_strdup (combinedname
);
211 mod
->filename
= g_strdup (libpath
);
214 if (g_slist_find_custom (ret
, mod
, mono_w32process_module_equals
) == NULL
) {
215 ret
= g_slist_prepend (ret
, mod
);
217 mono_w32process_module_free (mod
);
221 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_PROCESS
, "%s: Can't open process map file for pid %d", __func__
, pid
);
226 ret
= g_slist_reverse (ret
);
234 MonoW32ProcessModule
*mod
;
235 gchar buf
[MAXPATHLEN
+ 1], *p
, *endp
;
236 gchar
*start_start
, *end_start
, *prot_start
, *offset_start
;
237 gchar
*maj_dev_start
, *min_dev_start
, *inode_start
, prot_buf
[5];
238 gpointer address_start
, address_end
, address_offset
;
239 guint32 maj_dev
, min_dev
;
243 fp
= open_process_map (pid
, "r");
245 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_IO_LAYER_PROCESS
, "%s: Can't open process map file for pid %d", __func__
, pid
);
249 while (fgets (buf
, sizeof(buf
), fp
)) {
251 while (g_ascii_isspace (*p
)) ++p
;
253 if (!g_ascii_isxdigit (*start_start
)) {
256 address_start
= (gpointer
)strtoul (start_start
, &endp
, 16);
264 if (!g_ascii_isxdigit (*end_start
)) {
267 address_end
= (gpointer
)strtoul (end_start
, &endp
, 16);
269 if (!g_ascii_isspace (*p
)) {
273 while (g_ascii_isspace (*p
)) ++p
;
275 if (*prot_start
!= 'r' && *prot_start
!= '-') {
278 memcpy (prot_buf
, prot_start
, 4);
280 while (!g_ascii_isspace (*p
)) ++p
;
282 while (g_ascii_isspace (*p
)) ++p
;
284 if (!g_ascii_isxdigit (*offset_start
)) {
287 address_offset
= (gpointer
)strtoul (offset_start
, &endp
, 16);
289 if (!g_ascii_isspace (*p
)) {
293 while(g_ascii_isspace (*p
)) ++p
;
295 if (!g_ascii_isxdigit (*maj_dev_start
)) {
298 maj_dev
= strtoul (maj_dev_start
, &endp
, 16);
306 if (!g_ascii_isxdigit (*min_dev_start
)) {
309 min_dev
= strtoul (min_dev_start
, &endp
, 16);
311 if (!g_ascii_isspace (*p
)) {
315 while (g_ascii_isspace (*p
)) ++p
;
317 if (!g_ascii_isxdigit (*inode_start
)) {
320 inode
= (guint64
)strtol (inode_start
, &endp
, 10);
322 if (!g_ascii_isspace (*p
)) {
325 #if defined(MAJOR_IN_MKDEV) || defined(MAJOR_IN_SYSMACROS)
326 device
= makedev ((int)maj_dev
, (int)min_dev
);
332 if ((device
== 0) && (inode
== 0)) {
336 while(g_ascii_isspace (*p
)) ++p
;
337 /* p now points to the filename */
339 mod
= g_new0 (MonoW32ProcessModule
, 1);
340 mod
->address_start
= address_start
;
341 mod
->address_end
= address_end
;
342 mod
->perms
= g_strdup (prot_buf
);
343 mod
->address_offset
= address_offset
;
344 mod
->device
= device
;
346 mod
->filename
= g_strdup (g_strstrip (p
));
348 if (g_slist_find_custom (ret
, mod
, mono_w32process_module_equals
) == NULL
) {
349 ret
= g_slist_prepend (ret
, mod
);
351 mono_w32process_module_free (mod
);
355 ret
= g_slist_reverse (ret
);
364 mono_w32process_platform_init_once (void)