Completely replace mono_error_ok with is_ok and make first external_only. (#16217)
[mono-project.git] / mono / metadata / w32process-unix-bsd.c
blob38d10bbcd6404c44ea384d3dac068f30943bbeb3
1 /**
2 * \file
3 */
5 #include "w32process.h"
6 #include "w32process-unix-internals.h"
8 #ifdef USE_BSD_BACKEND
10 #include <errno.h>
11 #include <signal.h>
12 #include <sys/proc.h>
13 #include <sys/sysctl.h>
14 #if !defined(__OpenBSD__)
15 #include <sys/utsname.h>
16 #endif
17 #if defined(__FreeBSD__)
18 #include <sys/user.h> /* struct kinfo_proc */
19 #endif
21 #include <link.h>
22 #include "utils/mono-logger-internals.h"
23 #include "icall-decl.h"
25 gchar*
26 mono_w32process_get_name (pid_t pid)
28 gint mib [6];
29 gsize size;
30 struct kinfo_proc *pi;
31 gchar *ret = NULL;
33 #if defined(__FreeBSD__)
34 mib [0] = CTL_KERN;
35 mib [1] = KERN_PROC;
36 mib [2] = KERN_PROC_PID;
37 mib [3] = pid;
38 if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
39 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: sysctl() failed: %d", __func__, errno);
40 return NULL;
43 if ((pi = g_malloc (size)) == NULL)
44 return NULL;
46 if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
47 if (errno == ENOMEM) {
48 g_free (pi);
49 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Didn't allocate enough memory for kproc info", __func__);
51 return NULL;
54 ret = strlen (pi->ki_comm) > 0 ? g_strdup (pi->ki_comm) : NULL;
56 g_free (pi);
57 #elif defined(__OpenBSD__)
58 mib [0] = CTL_KERN;
59 mib [1] = KERN_PROC;
60 mib [2] = KERN_PROC_PID;
61 mib [3] = pid;
62 mib [4] = sizeof(struct kinfo_proc);
63 mib [5] = 0;
65 retry:
66 if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
67 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: sysctl() failed: %d", __func__, errno);
68 return NULL;
71 if ((pi = g_malloc (size)) == NULL)
72 return NULL;
74 mib[5] = (int)(size / sizeof(struct kinfo_proc));
76 if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) ||
77 (size != sizeof (struct kinfo_proc))) {
78 if (errno == ENOMEM) {
79 g_free (pi);
80 goto retry;
82 return NULL;
85 ret = strlen (pi->p_comm) > 0 ? g_strdup (pi->p_comm) : NULL;
87 g_free (pi);
88 #endif
90 return ret;
93 gchar*
94 mono_w32process_get_path (pid_t pid)
96 #if defined (__OpenBSD__)
97 // No KERN_PROC_PATHNAME on OpenBSD
98 return mono_w32process_get_name (pid);
99 #else
100 gsize path_len = PATH_MAX + 1;
101 gchar path [PATH_MAX + 1];
102 gint mib [4];
103 mib [0] = CTL_KERN;
104 #if defined (__NetBSD__)
105 mib [1] = KERN_PROC_ARGS;
106 mib [2] = pid;
107 mib [3] = KERN_PROC_PATHNAME;
108 #else // FreeBSD
109 mib [1] = KERN_PROC;
110 mib [2] = KERN_PROC_PATHNAME;
111 mib [3] = pid;
112 #endif
113 if (sysctl (mib, 4, path, &path_len, NULL, 0) < 0) {
114 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: sysctl() failed: %d", __func__, errno);
115 return NULL;
116 } else {
117 return g_strdup (path);
119 #endif
122 static gint
123 mono_w32process_get_modules_callback (struct dl_phdr_info *info, gsize size, gpointer ptr)
125 if (size < offsetof (struct dl_phdr_info, dlpi_phnum) + sizeof (info->dlpi_phnum))
126 return (-1);
128 struct dl_phdr_info *cpy = g_calloc (1, sizeof(struct dl_phdr_info));
129 if (!cpy)
130 return (-1);
132 memcpy(cpy, info, sizeof(*info));
134 g_ptr_array_add ((GPtrArray *)ptr, cpy);
136 return (0);
139 GSList*
140 mono_w32process_get_modules (pid_t pid)
142 GSList *ret = NULL;
143 MonoW32ProcessModule *mod;
144 GPtrArray *dlarray = g_ptr_array_new();
145 gint i;
147 if (dl_iterate_phdr (mono_w32process_get_modules_callback, dlarray) < 0)
148 return NULL;
150 for (i = 0; i < dlarray->len; i++) {
151 struct dl_phdr_info *info = g_ptr_array_index (dlarray, i);
153 mod = g_new0 (MonoW32ProcessModule, 1);
154 mod->address_start = (gpointer)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);
155 mod->address_end = (gpointer)(info->dlpi_addr + info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr);
156 mod->perms = g_strdup ("r--p");
157 mod->address_offset = 0;
158 mod->inode = i;
159 mod->filename = g_strdup (info->dlpi_name);
161 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p",
162 __func__, mod->inode, mod->filename, mod->address_start, mod->address_end);
164 g_free (info);
166 if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
167 ret = g_slist_prepend (ret, mod);
168 } else {
169 mono_w32process_module_free (mod);
173 g_ptr_array_free (dlarray, TRUE);
175 return g_slist_reverse (ret);
178 #endif