Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / w32process-unix-bsd.c
1 /**
2  * \file
3  */
4
5 #include "w32process.h"
6 #include "w32process-unix-internals.h"
7
8 #ifdef USE_BSD_BACKEND
9
10 #include <errno.h>
11 #include <sys/proc.h>
12 #include <sys/sysctl.h>
13 #if !defined(__OpenBSD__)
14 #include <sys/utsname.h>
15 #endif
16 #if defined(__FreeBSD__)
17 #include <sys/user.h> /* struct kinfo_proc */
18 #endif
19
20 #include <link.h>
21
22 #include "utils/mono-logger-internals.h"
23
24 gchar*
25 mono_w32process_get_name (pid_t pid)
26 {
27         gint mib [6];
28         gsize size;
29         struct kinfo_proc *pi;
30         gchar *ret = NULL;
31
32 #if defined(__FreeBSD__)
33         mib [0] = CTL_KERN;
34         mib [1] = KERN_PROC;
35         mib [2] = KERN_PROC_PID;
36         mib [3] = pid;
37         if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
38                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
39                 return NULL;
40         }
41
42         if ((pi = g_malloc (size)) == NULL)
43                 return NULL;
44
45         if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
46                 if (errno == ENOMEM) {
47                         g_free (pi);
48                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
49                 }
50                 return NULL;
51         }
52
53         ret = strlen (pi->ki_comm) > 0 ? g_strdup (pi->ki_comm) : NULL;
54
55         g_free (pi);
56 #elif defined(__OpenBSD__)
57         mib [0] = CTL_KERN;
58         mib [1] = KERN_PROC;
59         mib [2] = KERN_PROC_PID;
60         mib [3] = pid;
61         mib [4] = sizeof(struct kinfo_proc);
62         mib [5] = 0;
63
64 retry:
65         if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
66                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
67                 return NULL;
68         }
69
70         if ((pi = g_malloc (size)) == NULL)
71                 return NULL;
72
73         mib[5] = (int)(size / sizeof(struct kinfo_proc));
74
75         if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) ||
76                 (size != sizeof (struct kinfo_proc))) {
77                 if (errno == ENOMEM) {
78                         g_free (pi);
79                         goto retry;
80                 }
81                 return NULL;
82         }
83
84         ret = strlen (pi->p_comm) > 0 ? g_strdup (pi->p_comm) : NULL;
85
86         g_free (pi);
87 #endif
88
89         return ret;
90 }
91
92 gchar*
93 mono_w32process_get_path (pid_t pid)
94 {
95         return mono_w32process_get_name (pid);
96 }
97
98 static gint
99 mono_w32process_get_modules_callback (struct dl_phdr_info *info, gsize size, gpointer ptr)
100 {
101         if (size < offsetof (struct dl_phdr_info, dlpi_phnum) + sizeof (info->dlpi_phnum))
102                 return (-1);
103
104         struct dl_phdr_info *cpy = g_calloc (1, sizeof(struct dl_phdr_info));
105         if (!cpy)
106                 return (-1);
107
108         memcpy(cpy, info, sizeof(*info));
109
110         g_ptr_array_add ((GPtrArray *)ptr, cpy);
111
112         return (0);
113 }
114
115 GSList*
116 mono_w32process_get_modules (pid_t pid)
117 {
118         GSList *ret = NULL;
119         MonoW32ProcessModule *mod;
120         GPtrArray *dlarray = g_ptr_array_new();
121         gint i;
122
123         if (dl_iterate_phdr (mono_w32process_get_modules_callback, dlarray) < 0)
124                 return NULL;
125
126         for (i = 0; i < dlarray->len; i++) {
127                 struct dl_phdr_info *info = g_ptr_array_index (dlarray, i);
128
129                 mod = g_new0 (MonoW32ProcessModule, 1);
130                 mod->address_start = (gpointer)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);
131                 mod->address_end = (gpointer)(info->dlpi_addr + info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr);
132                 mod->perms = g_strdup ("r--p");
133                 mod->address_offset = 0;
134                 mod->inode = i;
135                 mod->filename = g_strdup (info->dlpi_name);
136
137                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p",
138                         __func__, mod->inode, mod->filename, mod->address_start, mod->address_end);
139
140                 g_free (info);
141
142                 if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
143                         ret = g_slist_prepend (ret, mod);
144                 } else {
145                         mono_w32process_module_free (mod);
146                 }
147         }
148
149         g_ptr_array_free (dlarray, TRUE);
150
151         return g_slist_reverse (ret);
152 }
153
154 #endif