2 /*--------------------------------------------------------------------*/
3 /*--- Startup: create initial process image on Darwin ---*/
4 /*--- initimg-darwin.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2007 Julian Seward
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.
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.
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
29 The GNU General Public License is contained in the file COPYING.
32 #if defined(VGO_darwin)
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 */
56 /*====================================================================*/
57 /*=== Loading the client ===*/
58 /*====================================================================*/
60 /* Load the client whose name is VG_(argv_the_exename). */
62 static void load_client ( /*OUT*/ExeInfo* info,
63 /*OUT*/Addr* client_ip)
69 vg_assert( VG_(args_the_exename) != NULL);
70 exe_name = ML_(find_executable)( VG_(args_the_exename) );
73 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
74 VG_(exit)(127); // 127 is Posix NOTFOUND
77 VG_(memset)(info, 0, sizeof(*info));
78 ret = VG_(do_exec)(exe_name, info);
80 // The client was successfully loaded! Continue.
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);
86 VG_(cl_exec_fd) = sr_Res(res);
88 /* Copy necessary bits of 'info' that were filled in */
89 *client_ip = info->init_ip;
93 /*====================================================================*/
94 /*=== Setting up the client's environment ===*/
95 /*====================================================================*/
97 /* Prepare the client's environment. This is basically a copy of our
100 DYLD_INSERT_LIBRARIES=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
101 ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
102 DYLD_INSERT_LIBRARIES
104 If this is missing, then it is added.
106 Also, remove any binding for VALGRIND_LAUNCHER=. The client should
107 not be able to see this.
109 Also, add DYLD_SHARED_REGION=avoid, because V doesn't know how
110 to process the dyld shared cache file.
112 Also, change VYLD_* (mangled by launcher) back to DYLD_*.
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.
117 static HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
119 HChar* preload_core = "vgpreload_core";
120 HChar* ld_preload = "DYLD_INSERT_LIBRARIES=";
121 HChar* dyld_cache = "DYLD_SHARED_REGION=";
122 HChar* dyld_cache_value= "avoid";
123 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));
133 HChar* preload_tool_path;
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
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);
148 /* Determine if there's a vgpreload_<tool>_<platform>.so file, and setup
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);
158 VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so",
159 VG_(libdir), preload_core, VG_PLATFORM);
161 VG_(free)(preload_tool_path);
163 VG_(debugLog)(2, "initimg", "preload_string:\n");
164 VG_(debugLog)(2, "initimg", " \"%s\"\n", preload_string);
166 /* Count the original size of the env */
168 for (cpp = origenv; cpp && *cpp; cpp++)
171 /* Allocate a new space */
172 ret = VG_(malloc) ("initimg-darwin.sce.3",
173 sizeof(HChar *) * (envc+2+1)); /* 2 new entries + NULL */
177 for (cpp = ret; *origenv; )
181 vg_assert(envc == (cpp - ret));
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);
190 VG_(snprintf)(cp, len, "%s%s:%s",
191 ld_preload, preload_string, (*cpp)+ld_preload_len);
195 ld_preload_done = True;
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);
202 VG_(snprintf)(cp, len, "%s%s", dyld_cache, dyld_cache_value);
206 ld_preload_done = True;
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);
216 VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
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);
225 VG_(snprintf)(cp, len, "%s%s", dyld_cache, dyld_cache_value);
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))
238 for (; i < envc-1; i++)
243 /* Change VYLD_ to DYLD */
244 for (i = 0; i < envc; i++) {
245 if (0 == VG_(strncmp)(ret[i], "VYLD_", 5)) {
251 VG_(free)(preload_string);
257 /*====================================================================*/
258 /*=== Setting up the client's stack ===*/
259 /*====================================================================*/
261 /* Add a string onto the string table, and return its address */
262 static char *copy_str(char **tab, const char *str)
272 VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
280 /* ----------------------------------------------------------------
282 This sets up the client's initial stack, containing the args,
283 environment and aux vector.
285 The format of the stack on Darwin is:
287 higher address +-----------------+ <- clstack_end
294 | executable_path | (first arg to execve())
306 | mach_header * | (dynamic only)
307 lower address +-----------------+ <- sp
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.
315 ---------------------------------------------------------------- */
318 Addr setup_client_stack( void* init_sp,
322 SizeT clstack_max_size )
325 char *strtab; /* string table */
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) */
338 vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
339 vg_assert( VG_(args_for_client) );
341 /* ==================== compute sizes ==================== */
343 /* first of all, work out how big the client stack will be */
346 have_exename = VG_(args_the_exename) != NULL;
348 /* paste on the extra args if the loader needs them (ie, the #!
349 interpreter and its argument) */
351 if (info->interp_name != NULL) {
353 stringsize += VG_(strlen)(info->interp_name) + 1;
355 if (info->interp_args != NULL) {
357 stringsize += VG_(strlen)(info->interp_args) + 1;
360 /* now scan the args we're given... */
362 stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
364 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
366 stringsize += VG_(strlen)( * (HChar**)
367 VG_(indexXA)( VG_(args_for_client), i ))
371 /* ...and the environment */
373 for (cpp = orig_envp; cpp && *cpp; cpp++) {
375 stringsize += VG_(strlen)(*cpp) + 1;
378 /* Darwin executable_path + NULL */
379 auxsize += 2 * sizeof(Word);
380 if (info->executable_path) {
381 stringsize += 1 + VG_(strlen)(info->executable_path);
384 /* Darwin mach_header */
385 if (info->dynamic) auxsize += sizeof(Word);
387 /* OK, now we know how big the client stack is */
389 sizeof(Word) + /* argc */
390 (have_exename ? sizeof(char **) : 0) + /* argc[0] == exename */
391 sizeof(char **)*argc + /* argv */
392 sizeof(char **) + /* terminal NULL */
393 sizeof(char **)*envc + /* envp */
394 sizeof(char **) + /* terminal NULL */
396 VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */
398 if (0) VG_(printf)("stacksize = %d\n", stacksize);
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 */
404 /* base of the string table (aligned) */
405 stringbase = strtab = (char *)clstack_end
406 - VG_ROUNDUP(stringsize, sizeof(int));
408 /* The max stack size */
409 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
411 /* Darwin stack is chosen by the ume loader */
412 clstack_start = clstack_end - clstack_max_size;
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;
420 VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n"
423 stringsize, auxsize, stacksize, (Int)clstack_max_size,
424 (void*)clstack_start, (void*)clstack_end);
426 /* ==================== allocate space ==================== */
428 /* Stack was allocated by the ume loader. */
430 /* ==================== create client stack ==================== */
432 ptr = (Addr*)client_SP;
434 /* --- mach_header --- */
435 if (info->dynamic) *ptr++ = info->text;
437 /* --- client argc --- */
438 *ptr++ = (Addr)(argc + (have_exename ? 1 : 0));
440 /* --- client argv --- */
441 if (info->interp_name) {
442 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
443 VG_(free)(info->interp_name);
445 if (info->interp_args) {
446 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
447 VG_(free)(info->interp_args);
451 *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
453 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
454 *ptr++ = (Addr)copy_str(
456 * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
462 VG_(client_envp) = (Char **)ptr;
463 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
464 *ptr = (Addr)copy_str(&strtab, *cpp);
467 /* --- executable_path + NULL --- */
468 if (info->executable_path)
469 *ptr++ = (Addr)copy_str(&strtab, info->executable_path);
474 vg_assert((strtab-stringbase) == stringsize);
476 /* client_SP is pointing at client's argc/argv */
478 if (0) VG_(printf)("startup SP = %#lx\n", client_SP);
483 /*====================================================================*/
484 /*=== Record system memory regions ===*/
485 /*====================================================================*/
487 static void record_system_memory(void)
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);
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);
503 # error unknown architecture
508 /*====================================================================*/
509 /*=== TOP-LEVEL: VG_(ii_create_image) ===*/
510 /*====================================================================*/
512 /* Create the client's initial memory image. */
513 IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii )
518 IIFinaliseImageInfo iifii;
519 VG_(memset)( &iifii, 0, sizeof(iifii) );
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");
528 if (VG_(args_the_exename) == NULL)
529 VG_(err_missing_prog)();
531 load_client(&info, &iifii.initial_client_IP);
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);
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;
549 iifii.initial_client_SP =
550 setup_client_stack( iicii.argv - 1, env, &info,
551 iicii.clstack_top, iifii.clstack_max_size );
555 VG_(debugLog)(2, "initimg",
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));
564 // Tell aspacem about commpage, etc
565 record_system_memory();
571 /*====================================================================*/
572 /*=== TOP-LEVEL: VG_(ii_finalise_image) ===*/
573 /*====================================================================*/
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).
581 void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
583 ThreadArchState* arch = &VG_(threads)[1].arch;
585 /* GrP fixme doesn't handle all registers from LC_THREAD or LC_UNIXTHREAD */
587 # if defined(VGP_x86_darwin)
588 vg_assert(0 == sizeof(VexGuestX86State) % 16);
590 /* Zero out the initial state, and set up the simulated FPU in a
592 LibVEX_GuestX86_initialise(&arch->vex);
594 /* Zero out the shadow areas. */
595 VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State));
596 VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State));
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;
602 # elif defined(VGP_amd64_darwin)
603 vg_assert(0 == sizeof(VexGuestAMD64State) % 16);
605 /* Zero out the initial state, and set up the simulated FPU in a
607 LibVEX_GuestAMD64_initialise(&arch->vex);
609 /* Zero out the shadow areas. */
610 VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State));
611 VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State));
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;
618 # error Unknown platform
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));
626 #endif // defined(VGO_darwin)
628 /*--------------------------------------------------------------------*/
630 /*--------------------------------------------------------------------*/