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