1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <stdlib.h> 6#include <string.h> 7#include <launchpad/launchpad.h> 8#include <launchpad/vmo.h> 9#include <lib/zircon-internal/crashlogger.h> 10#include <zircon/process.h> 11#include <zircon/syscalls.h> 12#include <zircon/syscalls/port.h> 13#include <zircon/status.h> 14#include <runtime/thread.h> 15#include <test-utils/test-utils.h> 16#include <unittest/unittest.h> 17 18#define TU_FAIL_ERRCODE 10 19 20void* tu_malloc(size_t size) 21{ 22 void* result = malloc(size); 23 if (result == NULL) { 24 // TODO(dje): printf may try to malloc too ... 25 unittest_printf_critical("out of memory trying to malloc(%zu)\n", size); 26 exit(TU_FAIL_ERRCODE); 27 } 28 return result; 29} 30 31void* tu_calloc(size_t nmemb, size_t size) 32{ 33 void* result = calloc(nmemb, size); 34 if (result == NULL) { 35 // TODO(dje): printf may try to malloc too ... 36 unittest_printf_critical("out of memory trying to calloc(%zu, %zu)\n", nmemb, size); 37 exit(TU_FAIL_ERRCODE); 38 } 39 return result; 40} 41 42char* tu_strdup(const char* s) 43{ 44 size_t len = strlen(s) + 1; 45 char* r = tu_malloc(len); 46 strcpy(r, s); 47 return r; 48} 49 50char* tu_asprintf(const char* fmt, ...) 51{ 52 va_list args; 53 char* result; 54 va_start(args, fmt); 55 if (vasprintf(&result, fmt, args) < 0) { 56 unittest_printf_critical("out of memory trying to asprintf(%s)\n", fmt); 57 exit(TU_FAIL_ERRCODE); 58 } 59 va_end(args); 60 return result; 61} 62 63void tu_fatal(const char *what, zx_status_t status) 64{ 65 const char* reason = zx_status_get_string(status); 66 unittest_printf_critical("\nFATAL: %s failed, rc %d (%s)\n", what, status, reason); 67 68 // Request a backtrace to assist debugging. 69 unittest_printf_critical("FATAL: backtrace follows:\n"); 70 unittest_printf_critical(" (using sw breakpoint request to crashlogger)\n"); 71 zx_crashlogger_request_backtrace(); 72 73 unittest_printf_critical("FATAL: exiting process\n"); 74 exit(TU_FAIL_ERRCODE); 75} 76 77void tu_handle_close(zx_handle_t handle) 78{ 79 zx_status_t status = zx_handle_close(handle); 80 // TODO(dje): It's still an open question as to whether errors other than ZX_ERR_BAD_HANDLE are "advisory". 81 if (status < 0) { 82 tu_fatal(__func__, status); 83 } 84} 85 86zx_handle_t tu_handle_duplicate(zx_handle_t handle) 87{ 88 zx_handle_t copy = ZX_HANDLE_INVALID; 89 zx_status_t status = 90 zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, ©); 91 if (status < 0) 92 tu_fatal(__func__, status); 93 return copy; 94} 95 96// N.B. This creates a C11 thread. 97// See, e.g., musl/include/threads.h. 98 99void tu_thread_create_c11(thrd_t* t, thrd_start_t entry, void* arg, 100 const char* name) 101{ 102 int ret = thrd_create_with_name(t, entry, arg, name); 103 if (ret != thrd_success) { 104 // tu_fatal takes zx_status_t values. 105 // The translation doesn't have to be perfect. 106 switch (ret) { 107 case thrd_nomem: 108 tu_fatal(__func__, ZX_ERR_NO_MEMORY); 109 default: 110 tu_fatal(__func__, ZX_ERR_BAD_STATE); 111 } 112 __UNREACHABLE; 113 } 114} 115 116zx_status_t tu_wait(uint32_t num_objects, 117 const zx_handle_t* handles, 118 const zx_signals_t* signals, 119 zx_signals_t* pending) 120{ 121 zx_wait_item_t items[num_objects]; 122 for (uint32_t n = 0; n < num_objects; n++) { 123 items[n].handle = handles[n]; 124 items[n].waitfor = signals[n]; 125 } 126 zx_status_t status = zx_object_wait_many(items, num_objects, ZX_TIME_INFINITE); 127 for (uint32_t n = 0; n < num_objects; n++) { 128 pending[n] = items[n].pending; 129 } 130 return status; 131} 132 133void tu_channel_create(zx_handle_t* handle0, zx_handle_t* handle1) { 134 zx_handle_t handles[2]; 135 zx_status_t status = zx_channel_create(0, &handles[0], &handles[1]); 136 if (status < 0) 137 tu_fatal(__func__, status); 138 *handle0 = handles[0]; 139 *handle1 = handles[1]; 140} 141 142void tu_channel_write(zx_handle_t handle, uint32_t flags, const void* bytes, uint32_t num_bytes, 143 const zx_handle_t* handles, uint32_t num_handles) { 144 zx_status_t status = zx_channel_write(handle, flags, bytes, num_bytes, handles, num_handles); 145 if (status < 0) 146 tu_fatal(__func__, status); 147} 148 149void tu_channel_read(zx_handle_t handle, uint32_t flags, void* bytes, uint32_t* num_bytes, 150 zx_handle_t* handles, uint32_t* num_handles) { 151 zx_status_t status = zx_channel_read(handle, flags, bytes, handles, 152 num_bytes ? *num_bytes : 0, num_handles ? *num_handles : 0, 153 num_bytes, num_handles); 154 if (status < 0) 155 tu_fatal(__func__, status); 156} 157 158bool tu_channel_wait_readable(zx_handle_t channel) 159{ 160 zx_signals_t signals = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED; 161 zx_signals_t pending; 162 zx_status_t result = tu_wait(1, &channel, &signals, &pending); 163 if (result != ZX_OK) 164 tu_fatal(__func__, result); 165 if ((pending & ZX_CHANNEL_READABLE) == 0) { 166 unittest_printf("%s: peer closed\n", __func__); 167 return false; 168 } 169 return true; 170} 171 172zx_handle_t tu_launch(zx_handle_t job, const char* name, 173 int argc, const char* const* argv, 174 const char* const* envp, 175 size_t num_handles, zx_handle_t* handles, 176 uint32_t* handle_ids) 177{ 178 launchpad_t* lp; 179 launchpad_create(job, name, &lp); 180 launchpad_load_from_file(lp, argv[0]); 181 launchpad_set_args(lp, argc, argv); 182 launchpad_set_environ(lp, envp); 183 launchpad_add_handles(lp, num_handles, handles, handle_ids); 184 185 zx_status_t status; 186 zx_handle_t child; 187 status = launchpad_go(lp, &child, NULL); 188 189 if (status < 0) 190 tu_fatal("tu_launch", status); 191 return child; 192} 193 194launchpad_t* tu_launch_fdio_init(zx_handle_t job, const char* name, 195 int argc, const char* const* argv, 196 const char* const* envp, 197 size_t hnds_count, zx_handle_t* handles, 198 uint32_t* ids) 199{ 200 // This is the first part of launchpad_launch_fdio_etc. 201 // It does everything except start the process running. 202 launchpad_t* lp; 203 204 const char* filename = argv[0]; 205 if (name == NULL) 206 name = filename; 207 208 launchpad_create(job, name, &lp); 209 launchpad_load_from_file(lp, filename); 210 launchpad_set_args(lp, argc, argv); 211 launchpad_set_environ(lp, envp); 212 launchpad_clone(lp, LP_CLONE_FDIO_ALL); 213 launchpad_add_handles(lp, hnds_count, handles, ids); 214 215 return lp; 216} 217 218zx_handle_t tu_launch_fdio_fini(launchpad_t* lp) 219{ 220 zx_handle_t proc; 221 zx_status_t status; 222 if ((status = launchpad_go(lp, &proc, NULL)) < 0) 223 tu_fatal("tu_launch_fdio_fini", status); 224 return proc; 225} 226 227void tu_process_wait_signaled(zx_handle_t process) 228{ 229 zx_signals_t signals = ZX_PROCESS_TERMINATED; 230 zx_signals_t pending; 231 zx_status_t result = tu_wait(1, &process, &signals, &pending); 232 if (result != ZX_OK) 233 tu_fatal(__func__, result); 234 if ((pending & ZX_PROCESS_TERMINATED) == 0) { 235 unittest_printf_critical("%s: unexpected return from tu_wait\n", __func__); 236 exit(TU_FAIL_ERRCODE); 237 } 238} 239 240bool tu_process_has_exited(zx_handle_t process) 241{ 242 zx_info_process_t info; 243 zx_status_t status; 244 if ((status = zx_object_get_info(process, ZX_INFO_PROCESS, &info, 245 sizeof(info), NULL, NULL)) < 0) 246 tu_fatal("get process info", status); 247 return info.exited; 248} 249 250int tu_process_get_return_code(zx_handle_t process) 251{ 252 zx_info_process_t info; 253 zx_status_t status; 254 if ((status = zx_object_get_info(process, ZX_INFO_PROCESS, &info, 255 sizeof(info), NULL, NULL)) < 0) 256 tu_fatal("get process info", status); 257 if (!info.exited) { 258 unittest_printf_critical( 259 "attempt to read return code of non-exited process"); 260 exit(TU_FAIL_ERRCODE); 261 } 262 return info.return_code; 263} 264 265int tu_process_wait_exit(zx_handle_t process) 266{ 267 tu_process_wait_signaled(process); 268 return tu_process_get_return_code(process); 269} 270 271zx_handle_t tu_process_get_thread(zx_handle_t process, zx_koid_t tid) 272{ 273 zx_handle_t thread; 274 zx_status_t status = zx_object_get_child(process, tid, ZX_RIGHT_SAME_RIGHTS, &thread); 275 if (status == ZX_ERR_NOT_FOUND) 276 return ZX_HANDLE_INVALID; 277 if (status < 0) 278 tu_fatal(__func__, status); 279 return thread; 280} 281 282size_t tu_process_get_threads(zx_handle_t process, zx_koid_t* threads, size_t max_threads) 283{ 284 size_t num_threads; 285 size_t buf_size = max_threads * sizeof(threads[0]); 286 zx_status_t status = zx_object_get_info(process, ZX_INFO_PROCESS_THREADS, 287 threads, buf_size, &num_threads, NULL); 288 if (status < 0) 289 tu_fatal(__func__, status); 290 return num_threads; 291} 292 293zx_handle_t tu_job_create(zx_handle_t job) 294{ 295 zx_handle_t child_job; 296 zx_status_t status = zx_job_create(job, 0, &child_job); 297 if (status < 0) 298 tu_fatal(__func__, status); 299 return child_job; 300} 301 302zx_handle_t tu_io_port_create(void) 303{ 304 zx_handle_t handle; 305 zx_status_t status = zx_port_create(0, &handle); 306 if (status < 0) 307 tu_fatal(__func__, status); 308 return handle; 309} 310 311void tu_set_exception_port(zx_handle_t handle, zx_handle_t eport, uint64_t key, uint32_t options) 312{ 313 if (handle == 0) 314 handle = zx_process_self(); 315 zx_status_t status = zx_task_bind_exception_port(handle, eport, key, options); 316 if (status < 0) 317 tu_fatal(__func__, status); 318} 319 320void tu_object_wait_async(zx_handle_t handle, zx_handle_t port, zx_signals_t signals) 321{ 322 uint64_t key = tu_get_koid(handle); 323 uint32_t options = ZX_WAIT_ASYNC_REPEATING; 324 zx_status_t status = zx_object_wait_async(handle, port, key, signals, options); 325 if (status < 0) 326 tu_fatal(__func__, status); 327} 328 329void tu_handle_get_basic_info(zx_handle_t handle, zx_info_handle_basic_t* info) 330{ 331 zx_status_t status = zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, 332 info, sizeof(*info), NULL, NULL); 333 if (status < 0) 334 tu_fatal(__func__, status); 335} 336 337zx_koid_t tu_get_koid(zx_handle_t handle) 338{ 339 zx_info_handle_basic_t info; 340 tu_handle_get_basic_info(handle, &info); 341 return info.koid; 342} 343 344zx_koid_t tu_get_related_koid(zx_handle_t handle) 345{ 346 zx_info_handle_basic_t info; 347 tu_handle_get_basic_info(handle, &info); 348 return info.related_koid; 349} 350 351zx_handle_t tu_get_thread(zx_handle_t proc, zx_koid_t tid) 352{ 353 zx_handle_t thread; 354 zx_status_t status = zx_object_get_child(proc, tid, ZX_RIGHT_SAME_RIGHTS, &thread); 355 if (status != ZX_OK) 356 tu_fatal(__func__, status); 357 return thread; 358} 359 360zx_info_thread_t tu_thread_get_info(zx_handle_t thread) 361{ 362 zx_info_thread_t info; 363 zx_status_t status = zx_object_get_info(thread, ZX_INFO_THREAD, &info, sizeof(info), NULL, NULL); 364 if (status < 0) 365 tu_fatal("zx_object_get_info(ZX_INFO_THREAD)", status); 366 return info; 367} 368 369uint32_t tu_thread_get_state(zx_handle_t thread) 370{ 371 zx_info_thread_t info = tu_thread_get_info(thread); 372 return info.state; 373} 374 375bool tu_thread_is_dying_or_dead(zx_handle_t thread) 376{ 377 zx_info_thread_t info = tu_thread_get_info(thread); 378 return (info.state == ZX_THREAD_STATE_DYING || 379 info.state == ZX_THREAD_STATE_DEAD); 380} 381 382void tu_task_kill(zx_handle_t task) 383{ 384 zx_status_t status = zx_task_kill(task); 385 if (status < 0) 386 tu_fatal("zx_task_kill", status); 387} 388 389int tu_run_program(const char *progname, int argc, const char** argv) 390{ 391 launchpad_t* lp; 392 393 unittest_printf("%s: running %s\n", __func__, progname); 394 395 launchpad_create(ZX_HANDLE_INVALID, progname, &lp); 396 launchpad_clone(lp, LP_CLONE_ALL); 397 launchpad_load_from_file(lp, argv[0]); 398 launchpad_set_args(lp, argc, argv); 399 zx_status_t status; 400 zx_handle_t child; 401 if ((status = launchpad_go(lp, &child, NULL)) < 0) { 402 tu_fatal(__func__, status); 403 } 404 405 int rc = tu_process_wait_exit(child); 406 tu_handle_close(child); 407 unittest_printf("%s: child returned %d\n", __func__, rc); 408 return rc; 409} 410 411int tu_run_command(const char* progname, const char* cmd) 412{ 413 const char* argv[] = { 414 "/boot/bin/sh", 415 "-c", 416 cmd 417 }; 418 419 return tu_run_program(progname, countof(argv), argv); 420} 421