Rizin
unix-like reverse engineering framework and cli tools
darwin.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  * Permission is hereby granted, free of charge, to any person obtaining a copy
3  * of this software and associated documentation files (the "Software"), to
4  * deal in the Software without restriction, including without limitation the
5  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6  * sell copies of the Software, and to permit persons to whom the Software is
7  * furnished to do so, subject to the following conditions:
8  *
9  * The above copyright notice and this permission notice shall be included in
10  * all copies or substantial portions of the Software.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18  * IN THE SOFTWARE.
19  */
20 
21 #include "uv.h"
22 #include "internal.h"
23 
24 #include <assert.h>
25 #include <stdint.h>
26 #include <errno.h>
27 
28 #include <dlfcn.h>
29 #include <mach/mach.h>
30 #include <mach/mach_time.h>
31 #include <mach-o/dyld.h> /* _NSGetExecutablePath */
32 #include <sys/resource.h>
33 #include <sys/sysctl.h>
34 #include <unistd.h> /* sysconf */
35 
36 #if !TARGET_OS_IPHONE
37 #include "darwin-stub.h"
38 #endif
39 
41 static uint64_t (*time_func)(void);
42 static mach_timebase_info_data_t timebase;
43 
44 typedef unsigned char UInt8;
45 
47  loop->cf_state = NULL;
48 
49  if (uv__kqueue_init(loop))
50  return UV__ERR(errno);
51 
52  return 0;
53 }
54 
55 
58 }
59 
60 
61 static void uv__hrtime_init_once(void) {
62  if (KERN_SUCCESS != mach_timebase_info(&timebase))
63  abort();
64 
65  time_func = (uint64_t (*)(void)) dlsym(RTLD_DEFAULT, "mach_continuous_time");
66  if (time_func == NULL)
67  time_func = mach_absolute_time;
68 }
69 
70 
73  return time_func() * timebase.numer / timebase.denom;
74 }
75 
76 
77 int uv_exepath(char* buffer, size_t* size) {
78  /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */
79  char abspath[PATH_MAX * 2 + 1];
80  char exepath[PATH_MAX + 1];
81  uint32_t exepath_size;
82  size_t abspath_size;
83 
84  if (buffer == NULL || size == NULL || *size == 0)
85  return UV_EINVAL;
86 
87  exepath_size = sizeof(exepath);
88  if (_NSGetExecutablePath(exepath, &exepath_size))
89  return UV_EIO;
90 
91  if (realpath(exepath, abspath) != abspath)
92  return UV__ERR(errno);
93 
94  abspath_size = strlen(abspath);
95  if (abspath_size == 0)
96  return UV_EIO;
97 
98  *size -= 1;
99  if (*size > abspath_size)
100  *size = abspath_size;
101 
102  memcpy(buffer, abspath, *size);
103  buffer[*size] = '\0';
104 
105  return 0;
106 }
107 
108 
110  vm_statistics_data_t info;
111  mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t);
112 
113  if (host_statistics(mach_host_self(), HOST_VM_INFO,
114  (host_info_t)&info, &count) != KERN_SUCCESS) {
115  return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
116  }
117 
118  return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE);
119 }
120 
121 
123  uint64_t info;
124  int which[] = {CTL_HW, HW_MEMSIZE};
125  size_t size = sizeof(info);
126 
127  if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
128  return UV__ERR(errno);
129 
130  return (uint64_t) info;
131 }
132 
133 
135  return 0; /* Memory constraints are unknown. */
136 }
137 
138 
139 void uv_loadavg(double avg[3]) {
140  struct loadavg info;
141  size_t size = sizeof(info);
142  int which[] = {CTL_VM, VM_LOADAVG};
143 
144  if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return;
145 
146  avg[0] = (double) info.ldavg[0] / info.fscale;
147  avg[1] = (double) info.ldavg[1] / info.fscale;
148  avg[2] = (double) info.ldavg[2] / info.fscale;
149 }
150 
151 
152 int uv_resident_set_memory(size_t* rss) {
153  mach_msg_type_number_t count;
154  task_basic_info_data_t info;
155  kern_return_t err;
156 
157  count = TASK_BASIC_INFO_COUNT;
158  err = task_info(mach_task_self(),
159  TASK_BASIC_INFO,
160  (task_info_t) &info,
161  &count);
162  (void) &err;
163  /* task_info(TASK_BASIC_INFO) cannot really fail. Anything other than
164  * KERN_SUCCESS implies a libuv bug.
165  */
166  assert(err == KERN_SUCCESS);
167  *rss = info.resident_size;
168 
169  return 0;
170 }
171 
172 
173 int uv_uptime(double* uptime) {
174  time_t now;
175  struct timeval info;
176  size_t size = sizeof(info);
177  static int which[] = {CTL_KERN, KERN_BOOTTIME};
178 
179  if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
180  return UV__ERR(errno);
181 
182  now = time(NULL);
183  *uptime = now - info.tv_sec;
184 
185  return 0;
186 }
187 
188 static int uv__get_cpu_speed(uint64_t* speed) {
189  /* IOKit */
190  void (*pIOObjectRelease)(io_object_t);
191  kern_return_t (*pIOMasterPort)(mach_port_t, mach_port_t*);
192  CFMutableDictionaryRef (*pIOServiceMatching)(const char*);
193  kern_return_t (*pIOServiceGetMatchingServices)(mach_port_t,
195  io_iterator_t*);
196  io_service_t (*pIOIteratorNext)(io_iterator_t);
197  CFTypeRef (*pIORegistryEntryCreateCFProperty)(io_registry_entry_t,
198  CFStringRef,
200  IOOptionBits);
201 
202  /* CoreFoundation */
203  CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
204  const char*,
206  CFStringEncoding (*pCFStringGetSystemEncoding)(void);
207  UInt8 *(*pCFDataGetBytePtr)(CFDataRef);
208  CFIndex (*pCFDataGetLength)(CFDataRef);
209  void (*pCFDataGetBytes)(CFDataRef, CFRange, UInt8*);
210  void (*pCFRelease)(CFTypeRef);
211 
212  void* core_foundation_handle;
213  void* iokit_handle;
214  int err;
215 
216  kern_return_t kr;
217  mach_port_t mach_port;
218  io_iterator_t it;
219  io_object_t service;
220 
221  mach_port = 0;
222 
223  err = UV_ENOENT;
224  core_foundation_handle = dlopen("/System/Library/Frameworks/"
225  "CoreFoundation.framework/"
226  "Versions/A/CoreFoundation",
227  RTLD_LAZY | RTLD_LOCAL);
228  iokit_handle = dlopen("/System/Library/Frameworks/IOKit.framework/"
229  "Versions/A/IOKit",
230  RTLD_LAZY | RTLD_LOCAL);
231 
232  if (core_foundation_handle == NULL || iokit_handle == NULL)
233  goto out;
234 
235 #define V(handle, symbol) \
236  do { \
237  *(void **)(&p ## symbol) = dlsym((handle), #symbol); \
238  if (p ## symbol == NULL) \
239  goto out; \
240  } \
241  while (0)
242  V(iokit_handle, IOMasterPort);
243  V(iokit_handle, IOServiceMatching);
244  V(iokit_handle, IOServiceGetMatchingServices);
245  V(iokit_handle, IOIteratorNext);
246  V(iokit_handle, IOObjectRelease);
247  V(iokit_handle, IORegistryEntryCreateCFProperty);
248  V(core_foundation_handle, CFStringCreateWithCString);
249  V(core_foundation_handle, CFStringGetSystemEncoding);
250  V(core_foundation_handle, CFDataGetBytePtr);
251  V(core_foundation_handle, CFDataGetLength);
252  V(core_foundation_handle, CFDataGetBytes);
253  V(core_foundation_handle, CFRelease);
254 #undef V
255 
256 #define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
257 
258  kr = pIOMasterPort(MACH_PORT_NULL, &mach_port);
259  assert(kr == KERN_SUCCESS);
260  CFMutableDictionaryRef classes_to_match
261  = pIOServiceMatching("IOPlatformDevice");
262  kr = pIOServiceGetMatchingServices(mach_port, classes_to_match, &it);
263  assert(kr == KERN_SUCCESS);
264  service = pIOIteratorNext(it);
265 
266  CFStringRef device_type_str = S("device_type");
267  CFStringRef clock_frequency_str = S("clock-frequency");
268 
269  while (service != 0) {
270  CFDataRef data;
271  data = pIORegistryEntryCreateCFProperty(service,
272  device_type_str,
273  NULL,
274  0);
275  if (data) {
276  const UInt8* raw = pCFDataGetBytePtr(data);
277  if (strncmp((char*)raw, "cpu", 3) == 0 ||
278  strncmp((char*)raw, "processor", 9) == 0) {
279  CFDataRef freq_ref;
280  freq_ref = pIORegistryEntryCreateCFProperty(service,
281  clock_frequency_str,
282  NULL,
283  0);
284  if (freq_ref) {
285  uint32_t freq;
286  CFIndex len = pCFDataGetLength(freq_ref);
287  CFRange range;
288  range.location = 0;
289  range.length = len;
290 
291  pCFDataGetBytes(freq_ref, range, (UInt8*)&freq);
292  *speed = freq;
293  pCFRelease(freq_ref);
294  pCFRelease(data);
295  break;
296  }
297  }
298  pCFRelease(data);
299  }
300 
301  service = pIOIteratorNext(it);
302  }
303 
304  pIOObjectRelease(it);
305 
306  err = 0;
307 out:
308  if (core_foundation_handle != NULL)
309  dlclose(core_foundation_handle);
310 
311  if (iokit_handle != NULL)
312  dlclose(iokit_handle);
313 
314  mach_port_deallocate(mach_task_self(), mach_port);
315 
316  return err;
317 }
318 
319 int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
320  unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
321  multiplier = ((uint64_t)1000L / ticks);
322  char model[512];
323  size_t size;
324  unsigned int i;
325  natural_t numcpus;
326  mach_msg_type_number_t msg_type;
327  processor_cpu_load_info_data_t *info;
328  uv_cpu_info_t* cpu_info;
329  uint64_t cpuspeed;
330  int err;
331 
332  size = sizeof(model);
333  if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) &&
334  sysctlbyname("hw.model", &model, &size, NULL, 0)) {
335  return UV__ERR(errno);
336  }
337 
338  err = uv__get_cpu_speed(&cpuspeed);
339  if (err < 0)
340  return err;
341 
342  if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
343  (processor_info_array_t*)&info,
344  &msg_type) != KERN_SUCCESS) {
345  return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
346  }
347 
348  *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
349  if (!(*cpu_infos)) {
350  vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
351  return UV_ENOMEM;
352  }
353 
354  *count = numcpus;
355 
356  for (i = 0; i < numcpus; i++) {
357  cpu_info = &(*cpu_infos)[i];
358 
359  cpu_info->cpu_times.user = (uint64_t)(info[i].cpu_ticks[0]) * multiplier;
360  cpu_info->cpu_times.nice = (uint64_t)(info[i].cpu_ticks[3]) * multiplier;
361  cpu_info->cpu_times.sys = (uint64_t)(info[i].cpu_ticks[1]) * multiplier;
362  cpu_info->cpu_times.idle = (uint64_t)(info[i].cpu_ticks[2]) * multiplier;
363  cpu_info->cpu_times.irq = 0;
364 
365  cpu_info->model = uv__strdup(model);
366  cpu_info->speed = cpuspeed/1000000;
367  }
368  vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
369 
370  return 0;
371 }
size_t len
Definition: 6502dis.c:15
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol which
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
unsigned int io_iterator_t
Definition: darwin-stub.h:57
long CFIndex
Definition: darwin-stub.h:36
void * CFDataRef
Definition: darwin-stub.h:46
unsigned int io_registry_entry_t
Definition: darwin-stub.h:60
void * CFMutableDictionaryRef
Definition: darwin-stub.h:48
unsigned int io_service_t
Definition: darwin-stub.h:59
void * CFStringRef
Definition: darwin-stub.h:52
void * CFAllocatorRef
Definition: darwin-stub.h:43
void * CFTypeRef
Definition: darwin-stub.h:53
unsigned int io_object_t
Definition: darwin-stub.h:58
uint32_t IOOptionBits
Definition: darwin-stub.h:56
struct CFRange CFRange
Definition: darwin-stub.h:49
unsigned CFStringEncoding
Definition: darwin-stub.h:42
#define UV__ERR(x)
Definition: errno.h:29
void uv__fsevents_loop_delete(uv_loop_t *loop)
Definition: fsevents.c:39
voidpf void uLong size
Definition: ioapi.h:138
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static static fork const void static count static fd const char const char static newpath char char char static envp time
Definition: sflib.h:42
int integer_t
Definition: mach0_specs.h:8
assert(limit<=UINT32_MAX/2)
int type
Definition: mipsasm.c:17
static int
Definition: sfsocketcall.h:114
unsigned int uint32_t
Definition: sftypes.h:29
unsigned long uint64_t
Definition: sftypes.h:28
int time_t
Definition: sftypes.h:66
Definition: buffer.h:15
struct uv_cpu_times_s cpu_times
Definition: uv.h:1093
char * model
Definition: uv.h:1091
int speed
Definition: uv.h:1092
uint64_t nice
Definition: uv.h:1084
uint64_t sys
Definition: uv.h:1085
uint64_t idle
Definition: uv.h:1086
uint64_t user
Definition: uv.h:1083
uint64_t irq
Definition: uv.h:1087
Definition: uv.h:1780
uv_loop_t * loop
Definition: main.c:7
uint64_t uv_get_total_memory(void)
Definition: darwin.c:122
static void uv__hrtime_init_once(void)
Definition: darwin.c:61
void uv_loadavg(double avg[3])
Definition: darwin.c:139
static uint64_t(* time_func)(void)
Definition: darwin.c:41
uint64_t uv_get_free_memory(void)
Definition: darwin.c:109
uint64_t uv__hrtime(uv_clocktype_t type)
Definition: darwin.c:71
int uv__platform_loop_init(uv_loop_t *loop)
Definition: darwin.c:46
#define S(s)
static uv_once_t once
Definition: darwin.c:40
int uv_uptime(double *uptime)
Definition: darwin.c:173
unsigned char UInt8
Definition: darwin.c:44
#define V(handle, symbol)
int uv_cpu_info(uv_cpu_info_t **cpu_infos, int *count)
Definition: darwin.c:319
uint64_t uv_get_constrained_memory(void)
Definition: darwin.c:134
void uv__platform_loop_delete(uv_loop_t *loop)
Definition: darwin.c:56
static int uv__get_cpu_speed(uint64_t *speed)
Definition: darwin.c:188
static mach_timebase_info_data_t timebase
Definition: darwin.c:42
int uv_exepath(char *buffer, size_t *size)
Definition: darwin.c:77
int uv_resident_set_memory(size_t *rss)
Definition: darwin.c:152
uv_clocktype_t
Definition: internal.h:146
int uv__kqueue_init(uv_loop_t *loop)
Definition: kqueue.c:51
pthread_once_t uv_once_t
Definition: unix.h:135
#define UV_ONCE_INIT
Definition: unix.h:133
char * uv__strdup(const char *s)
Definition: uv-common.c:55
void * uv__malloc(size_t size)
Definition: uv-common.c:75
UV_EXTERN void uv_once(uv_once_t *guard, void(*callback)(void))
Definition: thread.c:419