1 2/*--------------------------------------------------------------------*/ 3/*--- Startup: create initial process image on Darwin ---*/ 4/*--- initimg-darwin.c ---*/ 5/*--------------------------------------------------------------------*/ 6 7/* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2000-2015 Julian Seward 12 jseward@acm.org 13 14 This program is free software; you can redistribute it and/or 15 modify it under the terms of the GNU General Public License as 16 published by the Free Software Foundation; either version 2 of the 17 License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, but 20 WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 02111-1307, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30*/ 31 32#if defined(VGO_darwin) 33 34#include "pub_core_basics.h" 35#include "pub_core_vki.h" 36#include "pub_core_debuglog.h" 37#include "pub_core_libcbase.h" 38#include "pub_core_libcassert.h" 39#include "pub_core_libcfile.h" 40#include "pub_core_libcproc.h" 41#include "pub_core_libcprint.h" 42#include "pub_core_xarray.h" 43#include "pub_core_clientstate.h" 44#include "pub_core_aspacemgr.h" 45#include "pub_core_mallocfree.h" 46#include "pub_core_machine.h" 47#include "pub_core_ume.h" 48#include "pub_core_options.h" 49#include "pub_core_tooliface.h" /* VG_TRACK */ 50#include "pub_core_threadstate.h" /* ThreadArchState */ 51#include "priv_initimg_pathscan.h" 52#include "pub_core_initimg.h" /* self */ 53 54 55/*====================================================================*/ 56/*=== Loading the client ===*/ 57/*====================================================================*/ 58 59/* Load the client whose name is VG_(argv_the_exename). */ 60 61static void load_client ( /*OUT*/ExeInfo* info, 62 /*OUT*/Addr* client_ip) 63{ 64 const HChar* exe_name; 65 Int ret; 66 SysRes res; 67 68 vg_assert( VG_(args_the_exename) != NULL); 69 exe_name = ML_(find_executable)( VG_(args_the_exename) ); 70 71 if (!exe_name) { 72 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename)); 73 VG_(exit)(127); // 127 is Posix NOTFOUND 74 } 75 76 VG_(memset)(info, 0, sizeof(*info)); 77 ret = VG_(do_exec)(exe_name, info); 78 79 // The client was successfully loaded! Continue. 80 81 /* Get hold of a file descriptor which refers to the client 82 executable. This is needed for attaching to GDB. */ 83 res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); 84 if (!sr_isError(res)) 85 VG_(cl_exec_fd) = sr_Res(res); 86 87 /* Copy necessary bits of 'info' that were filled in */ 88 *client_ip = info->init_ip; 89} 90 91 92/*====================================================================*/ 93/*=== Setting up the client's environment ===*/ 94/*====================================================================*/ 95 96/* Prepare the client's environment. This is basically a copy of our 97 environment, except: 98 99 DYLD_INSERT_LIBRARIES=$VALGRIND_LIB/vgpreload_core-PLATFORM.so: 100 ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)? 101 DYLD_INSERT_LIBRARIES 102 103 If this is missing, then it is added. 104 105 Also, remove any binding for VALGRIND_LAUNCHER=. The client should 106 not be able to see this. 107 108 Also, add DYLD_SHARED_REGION=avoid, because V doesn't know how 109 to process the dyld shared cache file. 110 111 Also, change VYLD_* (mangled by launcher) back to DYLD_*. 112 113 If this needs to handle any more variables it should be hacked 114 into something table driven. The copy is VG_(malloc)'d space. 115*/ 116static HChar** setup_client_env ( HChar** origenv, const HChar* toolname) 117{ 118 const HChar* preload_core = "vgpreload_core"; 119 const HChar* ld_preload = "DYLD_INSERT_LIBRARIES="; 120 const HChar* dyld_cache = "DYLD_SHARED_REGION="; 121 const HChar* dyld_cache_value= "avoid"; 122 const HChar* v_launcher = VALGRIND_LAUNCHER "="; 123 Int ld_preload_len = VG_(strlen)( ld_preload ); 124 Int dyld_cache_len = VG_(strlen)( dyld_cache ); 125 Int v_launcher_len = VG_(strlen)( v_launcher ); 126 Bool ld_preload_done = False; 127 Bool dyld_cache_done = False; 128 Int vglib_len = VG_(strlen)(VG_(libdir)); 129 130 HChar** cpp; 131 HChar** ret; 132 HChar* preload_tool_path; 133 Int envc, i; 134 135 /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so 136 paths. We might not need the space for vgpreload_<tool>.so, but it 137 doesn't hurt to over-allocate briefly. The 16s are just cautious 138 slop. */ 139 Int preload_core_path_len = vglib_len + sizeof(preload_core) 140 + sizeof(VG_PLATFORM) + 16; 141 Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) 142 + sizeof(VG_PLATFORM) + 16; 143 Int preload_string_len = preload_core_path_len + preload_tool_path_len; 144 HChar* preload_string = VG_(malloc)("initimg-darwin.sce.1", preload_string_len); 145 146 /* Determine if there's a vgpreload_<tool>_<platform>.so file, and setup 147 preload_string. */ 148 preload_tool_path = VG_(malloc)("initimg-darwin.sce.2", preload_tool_path_len); 149 VG_(snprintf)(preload_tool_path, preload_tool_path_len, 150 "%s/vgpreload_%s-%s.so", VG_(libdir), toolname, VG_PLATFORM); 151 if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) { 152 VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so:%s", 153 VG_(libdir), preload_core, VG_PLATFORM, preload_tool_path); 154 } else { 155 VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so", 156 VG_(libdir), preload_core, VG_PLATFORM); 157 } 158 VG_(free)(preload_tool_path); 159 160 VG_(debugLog)(2, "initimg", "preload_string:\n"); 161 VG_(debugLog)(2, "initimg", " \"%s\"\n", preload_string); 162 163 /* Count the original size of the env */ 164 envc = 0; 165 for (cpp = origenv; cpp && *cpp; cpp++) 166 envc++; 167 168 /* Allocate a new space */ 169 ret = VG_(malloc) ("initimg-darwin.sce.3", 170 sizeof(HChar *) * (envc+2+1)); /* 2 new entries + NULL */ 171 172 /* copy it over */ 173 for (cpp = ret; *origenv; ) 174 *cpp++ = *origenv++; 175 *cpp = NULL; 176 177 vg_assert(envc == (cpp - ret)); 178 179 /* Walk over the new environment, mashing as we go */ 180 for (cpp = ret; cpp && *cpp; cpp++) { 181 if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) { 182 Int len = VG_(strlen)(*cpp) + preload_string_len; 183 HChar *cp = VG_(malloc)("initimg-darwin.sce.4", len); 184 185 VG_(snprintf)(cp, len, "%s%s:%s", 186 ld_preload, preload_string, (*cpp)+ld_preload_len); 187 188 *cpp = cp; 189 190 ld_preload_done = True; 191 } 192 if (VG_(memcmp)(*cpp, dyld_cache, dyld_cache_len) == 0) { 193 Int len = dyld_cache_len + VG_(strlen)(dyld_cache_value) + 1; 194 HChar *cp = VG_(malloc)("initimg-darwin.sce.4.2", len); 195 196 VG_(snprintf)(cp, len, "%s%s", dyld_cache, dyld_cache_value); 197 198 *cpp = cp; 199 200 ld_preload_done = True; 201 } 202 } 203 204 /* Add the missing bits */ 205 if (!ld_preload_done) { 206 Int len = ld_preload_len + preload_string_len; 207 HChar *cp = VG_(malloc) ("initimg-darwin.sce.5", len); 208 209 VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string); 210 211 ret[envc++] = cp; 212 } 213 if (!dyld_cache_done) { 214 Int len = dyld_cache_len + VG_(strlen)(dyld_cache_value) + 1; 215 HChar *cp = VG_(malloc) ("initimg-darwin.sce.5.2", len); 216 217 VG_(snprintf)(cp, len, "%s%s", dyld_cache, dyld_cache_value); 218 219 ret[envc++] = cp; 220 } 221 222 223 /* ret[0 .. envc-1] is live now. */ 224 /* Find and remove a binding for VALGRIND_LAUNCHER. */ 225 for (i = 0; i < envc; i++) 226 if (0 == VG_(memcmp)(ret[i], v_launcher, v_launcher_len)) 227 break; 228 229 if (i < envc) { 230 for (; i < envc-1; i++) 231 ret[i] = ret[i+1]; 232 envc--; 233 } 234 235 /* Change VYLD_ to DYLD */ 236 for (i = 0; i < envc; i++) { 237 if (0 == VG_(strncmp)(ret[i], "VYLD_", 5)) { 238 ret[i][0] = 'D'; 239 } 240 } 241 242 243 VG_(free)(preload_string); 244 ret[envc] = NULL; 245 return ret; 246} 247 248 249/*====================================================================*/ 250/*=== Setting up the client's stack ===*/ 251/*====================================================================*/ 252 253/* Add a string onto the string table, and return its address */ 254static HChar *copy_str(HChar **tab, const HChar *str) 255{ 256 HChar *cp = *tab; 257 HChar *orig = cp; 258 259 while(*str) 260 *cp++ = *str++; 261 *cp++ = '\0'; 262 263 if (0) 264 VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig)); 265 266 *tab = cp; 267 268 return orig; 269} 270 271 272/* ---------------------------------------------------------------- 273 274 This sets up the client's initial stack, containing the args, 275 environment and aux vector. 276 277 The format of the stack on Darwin is: 278 279 higher address +-----------------+ <- clstack_end 280 | | 281 : string table : 282 | | 283 +-----------------+ 284 | NULL | 285 +-----------------+ 286 | executable_path | (first arg to execve()) 287 +-----------------+ 288 | NULL | 289 - - 290 | envp | 291 +-----------------+ 292 | NULL | 293 - - 294 | argv | 295 +-----------------+ 296 | argc | 297 +-----------------+ 298 | mach_header * | (dynamic only) 299 lower address +-----------------+ <- sp 300 | undefined | 301 : : 302 303 Allocate and create the initial client stack. It is allocated down 304 from clstack_end, which was previously determined by the address 305 space manager. The returned value is the SP value for the client. 306 307 ---------------------------------------------------------------- */ 308 309static 310Addr setup_client_stack( void* init_sp, 311 HChar** orig_envp, 312 const ExeInfo* info, 313 Addr clstack_end, 314 SizeT clstack_max_size, 315 const VexArchInfo* vex_archinfo ) 316{ 317 HChar **cpp; 318 HChar *strtab; /* string table */ 319 HChar *stringbase; 320 Addr *ptr; 321 unsigned stringsize; /* total size of strings in bytes */ 322 unsigned auxsize; /* total size of auxv in bytes */ 323 Int argc; /* total argc */ 324 Int envc; /* total number of env vars */ 325 unsigned stacksize; /* total client stack size */ 326 Addr client_SP; /* client stack base (initial SP) */ 327 Addr clstack_start; 328 Int i; 329 330 vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1)); 331 vg_assert( VG_(args_for_client) ); 332 333 /* ==================== compute sizes ==================== */ 334 335 /* first of all, work out how big the client stack will be */ 336 stringsize = 0; 337 auxsize = 0; 338 339 /* paste on the extra args if the loader needs them (ie, the #! 340 interpreter and its argument) */ 341 argc = 0; 342 if (info->interp_name != NULL) { 343 argc++; 344 stringsize += VG_(strlen)(info->interp_name) + 1; 345 } 346 if (info->interp_args != NULL) { 347 argc++; 348 stringsize += VG_(strlen)(info->interp_args) + 1; 349 } 350 351 /* now scan the args we're given... */ 352 stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1; 353 354 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { 355 argc++; 356 stringsize += VG_(strlen)( * (HChar**) 357 VG_(indexXA)( VG_(args_for_client), i )) 358 + 1; 359 } 360 361 /* ...and the environment */ 362 envc = 0; 363 for (cpp = orig_envp; cpp && *cpp; cpp++) { 364 envc++; 365 stringsize += VG_(strlen)(*cpp) + 1; 366 } 367 368 /* Darwin executable_path + NULL */ 369 auxsize += 2 * sizeof(Word); 370 if (info->executable_path) { 371 stringsize += 1 + VG_(strlen)(info->executable_path); 372 } 373 374 /* Darwin mach_header */ 375 if (info->dynamic) auxsize += sizeof(Word); 376 377 /* OK, now we know how big the client stack is */ 378 stacksize = 379 sizeof(Word) + /* argc */ 380 sizeof(HChar **) + /* argc[0] == exename */ 381 sizeof(HChar **)*argc + /* argv */ 382 sizeof(HChar **) + /* terminal NULL */ 383 sizeof(HChar **)*envc + /* envp */ 384 sizeof(HChar **) + /* terminal NULL */ 385 auxsize + /* auxv */ 386 VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */ 387 388 if (0) VG_(printf)("stacksize = %d\n", stacksize); 389 390 /* client_SP is the client's stack pointer */ 391 client_SP = clstack_end + 1 - stacksize; 392 client_SP = VG_ROUNDDN(client_SP, 32); /* make stack 32 byte aligned */ 393 394 /* base of the string table (aligned) */ 395 stringbase = strtab = (HChar *)clstack_end 396 - VG_ROUNDUP(stringsize, sizeof(int)); 397 398 /* The max stack size */ 399 clstack_max_size = VG_PGROUNDUP(clstack_max_size); 400 401 /* Darwin stack is chosen by the ume loader */ 402 clstack_start = clstack_end + 1 - clstack_max_size; 403 404 /* Record stack extent -- needed for stack-change code. */ 405 /* GrP fixme really? */ 406 VG_(clstk_start_base) = clstack_start; 407 VG_(clstk_end) = clstack_end; 408 409 if (0) 410 VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n" 411 "clstack_start %p\n" 412 "clstack_end %p\n", 413 stringsize, auxsize, stacksize, (Int)clstack_max_size, 414 (void*)clstack_start, (void*)clstack_end); 415 416 /* ==================== allocate space ==================== */ 417 418 /* Stack was allocated by the ume loader. */ 419 420 /* ==================== create client stack ==================== */ 421 422 ptr = (Addr*)client_SP; 423 424 /* --- mach_header --- */ 425 if (info->dynamic) *ptr++ = info->text; 426 427 /* --- client argc --- */ 428 *ptr++ = (Addr)(argc + 1); 429 430 /* --- client argv --- */ 431 if (info->interp_name) { 432 *ptr++ = (Addr)copy_str(&strtab, info->interp_name); 433 VG_(free)(info->interp_name); 434 } 435 if (info->interp_args) { 436 *ptr++ = (Addr)copy_str(&strtab, info->interp_args); 437 VG_(free)(info->interp_args); 438 } 439 440 *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename)); 441 442 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { 443 *ptr++ = (Addr)copy_str( 444 &strtab, 445 * (HChar**) VG_(indexXA)( VG_(args_for_client), i ) 446 ); 447 } 448 *ptr++ = 0; 449 450 /* --- envp --- */ 451 VG_(client_envp) = (HChar **)ptr; 452 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++) 453 *ptr = (Addr)copy_str(&strtab, *cpp); 454 *ptr++ = 0; 455 456 /* --- executable_path + NULL --- */ 457 if (info->executable_path) 458 *ptr++ = (Addr)copy_str(&strtab, info->executable_path); 459 else 460 *ptr++ = 0; 461 *ptr++ = 0; 462 463 vg_assert((strtab-stringbase) == stringsize); 464 465 /* client_SP is pointing at client's argc/argv */ 466 467 if (0) VG_(printf)("startup SP = %#lx\n", client_SP); 468 return client_SP; 469} 470 471 472/*====================================================================*/ 473/*=== Record system memory regions ===*/ 474/*====================================================================*/ 475 476static void record_system_memory(void) 477{ 478 /* JRS 2014-Jul-08: this messes up the sync checker, because the 479 information that the kernel gives us doesn't include anything 480 about the commpage mapping. This functionality has therefore 481 been moved to m_main.c, valgrind_main(), section "Tell the tool 482 about the initial client memory permissions". See comments there 483 for rationale. */ 484 return; 485 /*NOTREACHED*/ 486 487 /* Tell aspacem where the client's kernel commpage is */ 488#if defined(VGA_amd64) 489 /* commpage 0x7fff:ffe00000+ - not in vm_region */ 490 // GrP fixme check again 491 VG_(am_notify_client_mmap)(0x7fffffe00000, 0x7ffffffff000-0x7fffffe00000, 492 VKI_PROT_READ|VKI_PROT_EXEC, 0, -1, 0); 493 494#elif defined(VGA_x86) 495 /* commpage 0xfffec000+ - not in vm_region */ 496 // GrP fixme check again 497 VG_(am_notify_client_mmap)(0xfffec000, 0xfffff000-0xfffec000, 498 VKI_PROT_READ|VKI_PROT_EXEC, 0, -1, 0); 499 500#else 501# error unknown architecture 502#endif 503} 504 505 506/*====================================================================*/ 507/*=== TOP-LEVEL: VG_(ii_create_image) ===*/ 508/*====================================================================*/ 509 510/* Create the client's initial memory image. */ 511IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii, 512 const VexArchInfo* vex_archinfo ) 513{ 514 ExeInfo info; 515 VG_(memset)( &info, 0, sizeof(info) ); 516 517 HChar** env = NULL; 518 519 IIFinaliseImageInfo iifii; 520 VG_(memset)( &iifii, 0, sizeof(iifii) ); 521 522 //-------------------------------------------------------------- 523 // Load client executable, finding in $PATH if necessary 524 // p: get_helprequest_and_toolname() [for 'exec', 'need_help'] 525 // p: layout_remaining_space [so there's space] 526 //-------------------------------------------------------------- 527 VG_(debugLog)(1, "initimg", "Loading client\n"); 528 529 if (VG_(args_the_exename) == NULL) 530 VG_(err_missing_prog)(); 531 532 load_client(&info, &iifii.initial_client_IP); 533 534 //-------------------------------------------------------------- 535 // Set up client's environment 536 // p: set-libdir [for VG_(libdir)] 537 // p: get_helprequest_and_toolname [for toolname] 538 //-------------------------------------------------------------- 539 VG_(debugLog)(1, "initimg", "Setup client env\n"); 540 env = setup_client_env(iicii.envp, iicii.toolname); 541 542 //-------------------------------------------------------------- 543 // Setup client stack, eip, and VG_(client_arg[cv]) 544 // p: load_client() [for 'info'] 545 // p: fix_environment() [for 'env'] 546 //-------------------------------------------------------------- 547 iicii.clstack_end = info.stack_end; 548 iifii.clstack_max_size = info.stack_end - info.stack_start + 1; 549 550 iifii.initial_client_SP = 551 setup_client_stack( iicii.argv - 1, env, &info, 552 iicii.clstack_end, iifii.clstack_max_size, 553 vex_archinfo ); 554 555 VG_(free)(env); 556 557 VG_(debugLog)(2, "initimg", 558 "Client info: " 559 "initial_IP=%p initial_SP=%p stack=[%p..%p]\n", 560 (void*)(iifii.initial_client_IP), 561 (void*)(iifii.initial_client_SP), 562 (void*)(info.stack_start), 563 (void*)(info.stack_end)); 564 565 566 // Tell aspacem about commpage, etc 567 record_system_memory(); 568 569 return iifii; 570} 571 572 573/*====================================================================*/ 574/*=== TOP-LEVEL: VG_(ii_finalise_image) ===*/ 575/*====================================================================*/ 576 577/* Just before starting the client, we may need to make final 578 adjustments to its initial image. Also we need to set up the VEX 579 guest state for thread 1 (the root thread) and copy in essential 580 starting values. This is handed the IIFinaliseImageInfo created by 581 VG_(ii_create_image). 582*/ 583void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) 584{ 585 ThreadArchState* arch = &VG_(threads)[1].arch; 586 587 /* GrP fixme doesn't handle all registers from LC_THREAD or LC_UNIXTHREAD */ 588 589# if defined(VGP_x86_darwin) 590 vg_assert(0 == sizeof(VexGuestX86State) % 16); 591 592 /* Zero out the initial state, and set up the simulated FPU in a 593 sane way. */ 594 LibVEX_GuestX86_initialise(&arch->vex); 595 596 /* Zero out the shadow areas. */ 597 VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State)); 598 VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State)); 599 600 /* Put essential stuff into the new state. */ 601 arch->vex.guest_ESP = iifii.initial_client_SP; 602 arch->vex.guest_EIP = iifii.initial_client_IP; 603 604# elif defined(VGP_amd64_darwin) 605 vg_assert(0 == sizeof(VexGuestAMD64State) % 16); 606 607 /* Zero out the initial state, and set up the simulated FPU in a 608 sane way. */ 609 LibVEX_GuestAMD64_initialise(&arch->vex); 610 611 /* Zero out the shadow areas. */ 612 VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State)); 613 VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State)); 614 615 /* Put essential stuff into the new state. */ 616 arch->vex.guest_RSP = iifii.initial_client_SP; 617 arch->vex.guest_RIP = iifii.initial_client_IP; 618 619# else 620# error Unknown platform 621# endif 622 623 /* Tell the tool that we just wrote to the registers. */ 624 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0, 625 sizeof(VexGuestArchState)); 626} 627 628#endif // defined(VGO_darwin) 629 630/*--------------------------------------------------------------------*/ 631/*--- end ---*/ 632/*--------------------------------------------------------------------*/ 633