1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/devtools/sharkctl.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,207 @@ 1.4 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifdef __APPLE__ 1.11 + 1.12 +#include "sharkctl.h" 1.13 +#include <stddef.h> 1.14 +#include <stdio.h> 1.15 +#include <stdlib.h> 1.16 +#include <unistd.h> 1.17 + 1.18 +#include "jsutil.h" 1.19 + 1.20 +#define SHARK_MSG_ACQUIRE 0x29a 1.21 +#define SHARK_MSG_RELEASE 0x29b 1.22 +#define SHARK_MSG_STOP 0x29c 1.23 +#define SHARK_MSG_START 0x29d 1.24 + 1.25 +#define RECV_SIZEOF(ty) offsetof(ty, out) 1.26 + 1.27 +// Private API in libSystem.dylib 1.28 +extern "C" void bootstrap_look_up(mach_port_t special_port, const char *name, 1.29 + mach_port_t *dest_port); 1.30 + 1.31 +struct chud_client_acquire_msg { 1.32 + mach_msg_header_t hdr; 1.33 + uint32_t unk0; // always 0 1.34 + uint32_t unk1; // always 1 1.35 + uint32_t pid; 1.36 + uint32_t out[2]; 1.37 +}; 1.38 + 1.39 +struct chud_client_start_msg { 1.40 + mach_msg_header_t hdr; 1.41 + uint32_t unk0; // always 1 1.42 + uint32_t name0; 1.43 + uint32_t arg2; // always 6 1.44 + uint8_t unk1; // always 0 1.45 + uint8_t unk2; // always 1 1.46 + uint8_t unk3; // uninitialized 1.47 + uint8_t unk4; // always 1 1.48 + uint32_t unk5; // always 0 1.49 + uint32_t unk6; // always 1 1.50 + uint32_t name1; // same as name0 1.51 +}; 1.52 + 1.53 +struct chud_client_stop_msg { 1.54 + mach_msg_header_t hdr; 1.55 + uint32_t out[5]; 1.56 +}; 1.57 + 1.58 +struct chud_client_release_msg { 1.59 + mach_msg_header_t hdr; 1.60 + uint32_t unk0; // always 0 1.61 + uint32_t unk1; // always 1 1.62 + uint32_t pid; 1.63 + uint32_t out[2]; 1.64 +}; 1.65 + 1.66 +static mach_port_t 1.67 +CreatePort(void) 1.68 +{ 1.69 + mach_port_t bootstrap_port, shark_port = 0; 1.70 + task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, 1.71 + &bootstrap_port); 1.72 + bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port); 1.73 + return shark_port; 1.74 +} 1.75 + 1.76 +static mach_msg_return_t 1.77 +Connect(mach_port_t shark_port) 1.78 +{ 1.79 + mach_port_t reply_port = mig_get_reply_port(); 1.80 + 1.81 + struct chud_client_acquire_msg msg; 1.82 + msg.hdr.msgh_bits = 0x1513; 1.83 + msg.hdr.msgh_size = sizeof(mach_msg_header_t); 1.84 + msg.hdr.msgh_remote_port = shark_port; 1.85 + msg.hdr.msgh_local_port = reply_port; 1.86 + msg.hdr.msgh_reserved = 0; 1.87 + msg.hdr.msgh_id = SHARK_MSG_ACQUIRE; 1.88 + msg.unk0 = 0; 1.89 + msg.unk1 = 1; 1.90 + msg.pid = getpid(); 1.91 + 1.92 + JS_ASSERT(RECV_SIZEOF(struct chud_client_acquire_msg) == 0x24); 1.93 + JS_ASSERT(sizeof(msg) == 0x2c); 1.94 + mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, 1.95 + RECV_SIZEOF(struct chud_client_acquire_msg), 1.96 + sizeof(msg), reply_port, 0, 0); 1.97 + mig_dealloc_reply_port(reply_port); 1.98 + return result; 1.99 +} 1.100 + 1.101 +static mach_msg_return_t 1.102 +Start(mach_port_t shark_port, uint32_t name) 1.103 +{ 1.104 + mach_port_t reply_port = mig_get_reply_port(); 1.105 + 1.106 + struct chud_client_start_msg msg; 1.107 + msg.hdr.msgh_bits = 0x80001513; 1.108 + msg.hdr.msgh_size = sizeof(mach_msg_header_t); 1.109 + msg.hdr.msgh_remote_port = shark_port; 1.110 + msg.hdr.msgh_local_port = reply_port; 1.111 + msg.hdr.msgh_reserved = 0; 1.112 + msg.hdr.msgh_id = SHARK_MSG_START; 1.113 + msg.unk0 = 1; 1.114 + msg.name0 = name; 1.115 + msg.arg2 = 6; 1.116 + msg.unk1 = 0; 1.117 + msg.unk2 = 1; 1.118 + msg.unk3 = 0; 1.119 + msg.unk4 = 1; 1.120 + msg.unk5 = 0; 1.121 + msg.unk6 = 1; 1.122 + msg.name1 = name; 1.123 + 1.124 + JS_ASSERT(sizeof(msg) == 0x34); 1.125 + mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, 1.126 + sizeof(msg), 0x30, reply_port, 0, 0); 1.127 + mig_dealloc_reply_port(reply_port); 1.128 + return result; 1.129 +} 1.130 + 1.131 +mach_msg_return_t 1.132 +Stop(mach_port_t shark_port) 1.133 +{ 1.134 + mach_port_t reply_port = mig_get_reply_port(); 1.135 + 1.136 + struct chud_client_stop_msg msg; 1.137 + msg.hdr.msgh_bits = 0x1513; 1.138 + msg.hdr.msgh_size = sizeof(mach_msg_header_t); 1.139 + msg.hdr.msgh_remote_port = shark_port; 1.140 + msg.hdr.msgh_local_port = reply_port; 1.141 + msg.hdr.msgh_reserved = 0; 1.142 + msg.hdr.msgh_id = SHARK_MSG_STOP; 1.143 + 1.144 + JS_ASSERT(RECV_SIZEOF(struct chud_client_stop_msg) == 0x18); 1.145 + JS_ASSERT(sizeof(msg) == 0x2c); 1.146 + mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, 1.147 + RECV_SIZEOF(struct chud_client_stop_msg), 1.148 + sizeof(msg), reply_port, 0, 0); 1.149 + mig_dealloc_reply_port(reply_port); 1.150 + return result; 1.151 +} 1.152 + 1.153 +static mach_msg_return_t 1.154 +Disconnect(mach_port_t shark_port) 1.155 +{ 1.156 + mach_port_t reply_port = mig_get_reply_port(); 1.157 + 1.158 + struct chud_client_release_msg msg; 1.159 + msg.hdr.msgh_bits = 0x1513; 1.160 + msg.hdr.msgh_size = sizeof(mach_msg_header_t); 1.161 + msg.hdr.msgh_remote_port = shark_port; 1.162 + msg.hdr.msgh_local_port = reply_port; 1.163 + msg.hdr.msgh_reserved = 0; 1.164 + msg.hdr.msgh_id = SHARK_MSG_RELEASE; 1.165 + msg.unk0 = 0; 1.166 + msg.unk1 = 1; 1.167 + msg.pid = getpid(); 1.168 + 1.169 + JS_ASSERT(RECV_SIZEOF(struct chud_client_release_msg) == 0x24); 1.170 + JS_ASSERT(sizeof(msg) == 0x2c); 1.171 + mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, 1.172 + RECV_SIZEOF(struct chud_client_release_msg), 1.173 + sizeof(msg), reply_port, 0, 0); 1.174 + mig_dealloc_reply_port(reply_port); 1.175 + return result; 1.176 +} 1.177 + 1.178 +static mach_port_t shark_port = 0; 1.179 +static bool connected = false; 1.180 +static bool running = false; 1.181 + 1.182 +namespace Shark { 1.183 + 1.184 +bool 1.185 +Start() 1.186 +{ 1.187 + if (!shark_port && !(shark_port = CreatePort())) 1.188 + return false; 1.189 + if (!connected && Connect(shark_port)) 1.190 + return false; 1.191 + connected = true; 1.192 + if (!running && ::Start(shark_port, 0xdeadbeef)) 1.193 + return false; 1.194 + return running = true; 1.195 +} 1.196 + 1.197 +void 1.198 +Stop() 1.199 +{ 1.200 + if (!shark_port || !connected) 1.201 + return; 1.202 + ::Stop(shark_port); 1.203 + running = false; 1.204 + Disconnect(shark_port); 1.205 + connected = false; 1.206 +} 1.207 + 1.208 +} 1.209 + 1.210 +#endif