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-2017 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, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #if defined(VGO_darwin)
32 #include "pub_core_basics.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_debuglog.h"
35 #include "pub_core_libcbase.h"
36 #include "pub_core_libcassert.h"
37 #include "pub_core_libcfile.h"
38 #include "pub_core_libcproc.h"
39 #include "pub_core_libcprint.h"
40 #include "pub_core_xarray.h"
41 #include "pub_core_clientstate.h"
42 #include "pub_core_aspacemgr.h"
43 #include "pub_core_mallocfree.h"
44 #include "pub_core_machine.h"
45 #include "pub_core_ume.h"
46 #include "pub_core_options.h"
47 #include "pub_core_tooliface.h" /* VG_TRACK */
48 #include "pub_core_threadstate.h" /* ThreadArchState */
49 #include "pub_core_pathscan.h" /* find_executable */
50 #include "pub_core_initimg.h" /* self */
53 /*====================================================================*/
54 /*=== Loading the client ===*/
55 /*====================================================================*/
57 /* Load the client whose name is VG_(argv_the_exename). */
59 static void load_client ( /*OUT*/ExeInfo
* info
,
60 /*OUT*/Addr
* client_ip
)
62 const HChar
* exe_name
;
66 vg_assert( VG_(args_the_exename
) != NULL
);
67 exe_name
= VG_(find_executable
)( VG_(args_the_exename
) );
70 VG_(printf
)("valgrind: %s: command not found\n", VG_(args_the_exename
));
71 VG_(exit
)(127); // 127 is Posix NOTFOUND
74 VG_(memset
)(info
, 0, sizeof(*info
));
75 ret
= VG_(do_exec
)(exe_name
, info
);
77 // The client was successfully loaded! Continue.
79 /* Get hold of a file descriptor which refers to the client
80 executable. This is needed for attaching to GDB. */
81 res
= VG_(open
)(exe_name
, VKI_O_RDONLY
, VKI_S_IRUSR
);
83 VG_(cl_exec_fd
) = sr_Res(res
);
85 /* Copy necessary bits of 'info' that were filled in */
86 *client_ip
= info
->init_ip
;
90 /*====================================================================*/
91 /*=== Setting up the client's environment ===*/
92 /*====================================================================*/
94 /* Prepare the client's environment. This is basically a copy of our
97 DYLD_INSERT_LIBRARIES=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
98 ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
101 If this is missing, then it is added.
103 Also, remove any binding for VALGRIND_LAUNCHER=. The client should
104 not be able to see this.
106 Also, add DYLD_SHARED_REGION=avoid, because V doesn't know how
107 to process the dyld shared cache file.
109 Also, change VYLD_* (mangled by launcher) back to DYLD_*.
111 If this needs to handle any more variables it should be hacked
112 into something table driven. The copy is VG_(malloc)'d space.
114 static HChar
** setup_client_env ( HChar
** origenv
, const HChar
* toolname
)
116 const HChar
* preload_core
= "vgpreload_core";
117 const HChar
* ld_preload
= "DYLD_INSERT_LIBRARIES=";
118 const HChar
* dyld_cache
= "DYLD_SHARED_REGION=";
119 const HChar
* dyld_cache_value
= "avoid";
120 const HChar
* v_launcher
= VALGRIND_LAUNCHER
"=";
121 Int ld_preload_len
= VG_(strlen
)( ld_preload
);
122 Int dyld_cache_len
= VG_(strlen
)( dyld_cache
);
123 Int v_launcher_len
= VG_(strlen
)( v_launcher
);
124 Bool ld_preload_done
= False
;
125 Bool dyld_cache_done
= False
;
126 Int vglib_len
= VG_(strlen
)(VG_(libdir
));
130 HChar
* preload_tool_path
;
133 /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
134 paths. We might not need the space for vgpreload_<tool>.so, but it
135 doesn't hurt to over-allocate briefly. The 16s are just cautious
137 Int preload_core_path_len
= vglib_len
+ VG_(strlen
)(preload_core
)
138 + sizeof(VG_PLATFORM
) + 16;
139 Int preload_tool_path_len
= vglib_len
+ VG_(strlen
)(toolname
)
140 + sizeof(VG_PLATFORM
) + 16;
141 Int preload_string_len
= preload_core_path_len
+ preload_tool_path_len
;
142 HChar
* preload_string
= VG_(malloc
)("initimg-darwin.sce.1", preload_string_len
);
144 /* Determine if there's a vgpreload_<tool>_<platform>.so file, and setup
146 preload_tool_path
= VG_(malloc
)("initimg-darwin.sce.2", preload_tool_path_len
);
147 VG_(snprintf
)(preload_tool_path
, preload_tool_path_len
,
148 "%s/vgpreload_%s-%s.so", VG_(libdir
), toolname
, VG_PLATFORM
);
149 if (VG_(access
)(preload_tool_path
, True
/*r*/, False
/*w*/, False
/*x*/) == 0) {
150 VG_(snprintf
)(preload_string
, preload_string_len
, "%s/%s-%s.so:%s",
151 VG_(libdir
), preload_core
, VG_PLATFORM
, preload_tool_path
);
153 VG_(snprintf
)(preload_string
, preload_string_len
, "%s/%s-%s.so",
154 VG_(libdir
), preload_core
, VG_PLATFORM
);
156 VG_(free
)(preload_tool_path
);
158 VG_(debugLog
)(2, "initimg", "preload_string:\n");
159 VG_(debugLog
)(2, "initimg", " \"%s\"\n", preload_string
);
161 /* Count the original size of the env */
163 for (cpp
= origenv
; cpp
&& *cpp
; cpp
++)
166 /* Allocate a new space */
167 ret
= VG_(malloc
) ("initimg-darwin.sce.3",
168 sizeof(HChar
*) * (envc
+2+1)); /* 2 new entries + NULL */
171 for (cpp
= ret
; *origenv
; )
175 vg_assert(envc
== (cpp
- ret
));
177 /* Walk over the new environment, mashing as we go */
178 for (cpp
= ret
; cpp
&& *cpp
; cpp
++) {
179 if (VG_(memcmp
)(*cpp
, ld_preload
, ld_preload_len
) == 0) {
180 Int len
= VG_(strlen
)(*cpp
) + preload_string_len
;
181 HChar
*cp
= VG_(malloc
)("initimg-darwin.sce.4", len
);
183 VG_(snprintf
)(cp
, len
, "%s%s:%s",
184 ld_preload
, preload_string
, (*cpp
)+ld_preload_len
);
188 ld_preload_done
= True
;
190 if (VG_(memcmp
)(*cpp
, dyld_cache
, dyld_cache_len
) == 0) {
191 Int len
= dyld_cache_len
+ VG_(strlen
)(dyld_cache_value
) + 1;
192 HChar
*cp
= VG_(malloc
)("initimg-darwin.sce.4.2", len
);
194 VG_(snprintf
)(cp
, len
, "%s%s", dyld_cache
, dyld_cache_value
);
198 ld_preload_done
= True
;
202 /* Add the missing bits */
203 if (!ld_preload_done
) {
204 Int len
= ld_preload_len
+ preload_string_len
;
205 HChar
*cp
= VG_(malloc
) ("initimg-darwin.sce.5", len
);
207 VG_(snprintf
)(cp
, len
, "%s%s", ld_preload
, preload_string
);
211 if (!dyld_cache_done
) {
212 Int len
= dyld_cache_len
+ VG_(strlen
)(dyld_cache_value
) + 1;
213 HChar
*cp
= VG_(malloc
) ("initimg-darwin.sce.5.2", len
);
215 VG_(snprintf
)(cp
, len
, "%s%s", dyld_cache
, dyld_cache_value
);
221 /* ret[0 .. envc-1] is live now. */
222 /* Find and remove a binding for VALGRIND_LAUNCHER. */
223 for (i
= 0; i
< envc
; i
++)
224 if (0 == VG_(memcmp
)(ret
[i
], v_launcher
, v_launcher_len
))
228 for (; i
< envc
-1; i
++)
233 /* Change VYLD_ to DYLD */
234 for (i
= 0; i
< envc
; i
++) {
235 if (0 == VG_(strncmp
)(ret
[i
], "VYLD_", 5)) {
241 VG_(free
)(preload_string
);
247 /*====================================================================*/
248 /*=== Setting up the client's stack ===*/
249 /*====================================================================*/
251 /* Add a string onto the string table, and return its address */
252 static HChar
*copy_str(HChar
**tab
, const HChar
*str
)
262 VG_(printf
)("copied %p \"%s\" len %lld\n", orig
, orig
, (Long
)(cp
-orig
));
270 /* ----------------------------------------------------------------
272 This sets up the client's initial stack, containing the args,
273 environment and aux vector.
275 The format of the stack on Darwin is:
277 higher address +-----------------+ <- clstack_end
284 | executable_path | (first arg to execve())
296 | mach_header * | (dynamic only)
297 lower address +-----------------+ <- sp
301 Allocate and create the initial client stack. It is allocated down
302 from clstack_end, which was previously determined by the address
303 space manager. The returned value is the SP value for the client.
305 ---------------------------------------------------------------- */
308 Addr
setup_client_stack( void* init_sp
,
312 SizeT clstack_max_size
,
313 const VexArchInfo
* vex_archinfo
)
316 HChar
*strtab
; /* string table */
319 unsigned stringsize
; /* total size of strings in bytes */
320 unsigned auxsize
; /* total size of auxv in bytes */
321 Int argc
; /* total argc */
322 Int envc
; /* total number of env vars */
323 unsigned stacksize
; /* total client stack size */
324 Addr client_SP
; /* client stack base (initial SP) */
328 vg_assert(VG_IS_PAGE_ALIGNED(clstack_end
+1));
329 vg_assert( VG_(args_for_client
) );
331 /* ==================== compute sizes ==================== */
333 /* first of all, work out how big the client stack will be */
337 /* paste on the extra args if the loader needs them (ie, the #!
338 interpreter and its argument) */
340 if (info
->interp_name
!= NULL
) {
342 stringsize
+= VG_(strlen
)(info
->interp_name
) + 1;
344 if (info
->interp_args
!= NULL
) {
346 stringsize
+= VG_(strlen
)(info
->interp_args
) + 1;
349 /* now scan the args we're given... */
350 stringsize
+= VG_(strlen
)( VG_(args_the_exename
) ) + 1;
352 for (i
= 0; i
< VG_(sizeXA
)( VG_(args_for_client
) ); i
++) {
354 stringsize
+= VG_(strlen
)( * (HChar
**)
355 VG_(indexXA
)( VG_(args_for_client
), i
))
359 /* ...and the environment */
361 for (cpp
= orig_envp
; cpp
&& *cpp
; cpp
++) {
363 stringsize
+= VG_(strlen
)(*cpp
) + 1;
366 /* Darwin executable_path + NULL */
367 auxsize
+= 2 * sizeof(Word
);
368 if (info
->executable_path
) {
369 stringsize
+= 1 + VG_(strlen
)(info
->executable_path
);
372 /* Darwin mach_header */
373 if (info
->dynamic
) auxsize
+= sizeof(Word
);
375 /* OK, now we know how big the client stack is */
377 sizeof(Word
) + /* argc */
378 sizeof(HChar
**) + /* argc[0] == exename */
379 sizeof(HChar
**)*argc
+ /* argv */
380 sizeof(HChar
**) + /* terminal NULL */
381 sizeof(HChar
**)*envc
+ /* envp */
382 sizeof(HChar
**) + /* terminal NULL */
384 VG_ROUNDUP(stringsize
, sizeof(Word
)); /* strings (aligned) */
386 if (0) VG_(printf
)("stacksize = %d\n", stacksize
);
388 /* client_SP is the client's stack pointer */
389 client_SP
= clstack_end
+ 1 - stacksize
;
390 client_SP
= VG_ROUNDDN(client_SP
, 32); /* make stack 32 byte aligned */
392 /* base of the string table (aligned) */
393 stringbase
= strtab
= (HChar
*)clstack_end
394 - VG_ROUNDUP(stringsize
, sizeof(int));
396 /* The max stack size */
397 clstack_max_size
= VG_PGROUNDUP(clstack_max_size
);
399 /* Darwin stack is chosen by the ume loader */
400 clstack_start
= clstack_end
+ 1 - clstack_max_size
;
402 /* Record stack extent -- needed for stack-change code. */
403 /* GrP fixme really? */
404 VG_(clstk_start_base
) = clstack_start
;
405 VG_(clstk_end
) = clstack_end
;
408 VG_(printf
)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n"
411 stringsize
, auxsize
, stacksize
, (Int
)clstack_max_size
,
412 (void*)clstack_start
, (void*)clstack_end
);
414 /* ==================== allocate space ==================== */
416 /* Stack was allocated by the ume loader. */
418 /* ==================== create client stack ==================== */
420 ptr
= (Addr
*)client_SP
;
422 /* --- mach_header --- */
423 if (info
->dynamic
) *ptr
++ = info
->text
;
425 /* --- client argc --- */
426 *ptr
++ = (Addr
)(argc
+ 1);
428 /* --- client argv --- */
429 if (info
->interp_name
)
430 *ptr
++ = (Addr
)copy_str(&strtab
, info
->interp_name
);
431 if (info
->interp_args
)
432 *ptr
++ = (Addr
)copy_str(&strtab
, info
->interp_args
);
434 *ptr
++ = (Addr
)copy_str(&strtab
, VG_(args_the_exename
));
436 for (i
= 0; i
< VG_(sizeXA
)( VG_(args_for_client
) ); i
++) {
437 *ptr
++ = (Addr
)copy_str(
439 * (HChar
**) VG_(indexXA
)( VG_(args_for_client
), i
)
445 VG_(client_envp
) = (HChar
**)ptr
;
446 for (cpp
= orig_envp
; cpp
&& *cpp
; ptr
++, cpp
++)
447 *ptr
= (Addr
)copy_str(&strtab
, *cpp
);
450 /* --- executable_path + NULL --- */
451 if (info
->executable_path
)
452 *ptr
++ = (Addr
)copy_str(&strtab
, info
->executable_path
);
457 vg_assert((strtab
-stringbase
) == stringsize
);
459 /* client_SP is pointing at client's argc/argv */
461 if (0) VG_(printf
)("startup SP = %#lx\n", client_SP
);
466 /*====================================================================*/
467 /*=== Record system memory regions ===*/
468 /*====================================================================*/
470 static void record_system_memory(void)
472 /* JRS 2014-Jul-08: this messes up the sync checker, because the
473 information that the kernel gives us doesn't include anything
474 about the commpage mapping. This functionality has therefore
475 been moved to m_main.c, valgrind_main(), section "Tell the tool
476 about the initial client memory permissions". See comments there
481 /* Tell aspacem where the client's kernel commpage is */
482 #if defined(VGA_amd64)
483 /* commpage 0x7fff:ffe00000+ - not in vm_region */
484 // GrP fixme check again
485 VG_(am_notify_client_mmap
)(0x7fffffe00000, 0x7ffffffff000-0x7fffffe00000,
486 VKI_PROT_READ
|VKI_PROT_EXEC
, 0, -1, 0);
488 #elif defined(VGA_x86)
489 /* commpage 0xfffec000+ - not in vm_region */
490 // GrP fixme check again
491 VG_(am_notify_client_mmap
)(0xfffec000, 0xfffff000-0xfffec000,
492 VKI_PROT_READ
|VKI_PROT_EXEC
, 0, -1, 0);
495 # error unknown architecture
500 /*====================================================================*/
501 /*=== TOP-LEVEL: VG_(ii_create_image) ===*/
502 /*====================================================================*/
504 /* Create the client's initial memory image. */
505 IIFinaliseImageInfo
VG_(ii_create_image
)( IICreateImageInfo iicii
,
506 const VexArchInfo
* vex_archinfo
)
509 VG_(memset
)( &info
, 0, sizeof(info
) );
513 IIFinaliseImageInfo iifii
;
514 VG_(memset
)( &iifii
, 0, sizeof(iifii
) );
516 //--------------------------------------------------------------
517 // Load client executable, finding in $PATH if necessary
518 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
519 // p: layout_remaining_space [so there's space]
520 //--------------------------------------------------------------
521 VG_(debugLog
)(1, "initimg", "Loading client\n");
523 if (VG_(args_the_exename
) == NULL
)
524 VG_(err_missing_prog
)();
526 load_client(&info
, &iifii
.initial_client_IP
);
528 //--------------------------------------------------------------
529 // Set up client's environment
530 // p: set-libdir [for VG_(libdir)]
531 // p: get_helprequest_and_toolname [for toolname]
532 //--------------------------------------------------------------
533 VG_(debugLog
)(1, "initimg", "Setup client env\n");
534 env
= setup_client_env(iicii
.envp
, iicii
.toolname
);
536 //--------------------------------------------------------------
537 // Setup client stack, eip, and VG_(client_arg[cv])
538 // p: load_client() [for 'info']
539 // p: fix_environment() [for 'env']
540 //--------------------------------------------------------------
541 iicii
.clstack_end
= info
.stack_end
;
542 iifii
.clstack_max_size
= info
.stack_end
- info
.stack_start
+ 1;
544 iifii
.initial_client_SP
=
545 setup_client_stack( iicii
.argv
- 1, env
, &info
,
546 iicii
.clstack_end
, iifii
.clstack_max_size
,
551 VG_(debugLog
)(2, "initimg",
553 "initial_IP=%p initial_SP=%p stack=[%p..%p]\n",
554 (void*)(iifii
.initial_client_IP
),
555 (void*)(iifii
.initial_client_SP
),
556 (void*)(info
.stack_start
),
557 (void*)(info
.stack_end
));
560 // Tell aspacem about commpage, etc
561 record_system_memory();
563 VG_(free
)(info
.interp_name
); info
.interp_name
= NULL
;
564 VG_(free
)(info
.interp_args
); info
.interp_args
= NULL
;
569 /*====================================================================*/
570 /*=== TOP-LEVEL: VG_(ii_finalise_image) ===*/
571 /*====================================================================*/
573 /* Just before starting the client, we may need to make final
574 adjustments to its initial image. Also we need to set up the VEX
575 guest state for thread 1 (the root thread) and copy in essential
576 starting values. This is handed the IIFinaliseImageInfo created by
577 VG_(ii_create_image).
579 void VG_(ii_finalise_image
)( IIFinaliseImageInfo iifii
)
581 ThreadArchState
* arch
= &VG_(threads
)[1].arch
;
583 /* GrP fixme doesn't handle all registers from LC_THREAD or LC_UNIXTHREAD */
585 # if defined(VGP_x86_darwin)
586 vg_assert(0 == sizeof(VexGuestX86State
) % 16);
588 /* Zero out the initial state, and set up the simulated FPU in a
590 LibVEX_GuestX86_initialise(&arch
->vex
);
592 /* Zero out the shadow areas. */
593 VG_(memset
)(&arch
->vex_shadow1
, 0, sizeof(VexGuestX86State
));
594 VG_(memset
)(&arch
->vex_shadow2
, 0, sizeof(VexGuestX86State
));
596 /* Put essential stuff into the new state. */
597 arch
->vex
.guest_ESP
= iifii
.initial_client_SP
;
598 arch
->vex
.guest_EIP
= iifii
.initial_client_IP
;
600 # elif defined(VGP_amd64_darwin)
601 vg_assert(0 == sizeof(VexGuestAMD64State
) % 16);
603 /* Zero out the initial state, and set up the simulated FPU in a
605 LibVEX_GuestAMD64_initialise(&arch
->vex
);
607 /* Zero out the shadow areas. */
608 VG_(memset
)(&arch
->vex_shadow1
, 0, sizeof(VexGuestAMD64State
));
609 VG_(memset
)(&arch
->vex_shadow2
, 0, sizeof(VexGuestAMD64State
));
611 /* Put essential stuff into the new state. */
612 arch
->vex
.guest_RSP
= iifii
.initial_client_SP
;
613 arch
->vex
.guest_RIP
= iifii
.initial_client_IP
;
616 # error Unknown platform
619 /* Tell the tool that we just wrote to the registers. */
620 VG_TRACK( post_reg_write
, Vg_CoreStartup
, /*tid*/1, /*offset*/0,
621 sizeof(VexGuestArchState
));
624 #endif // defined(VGO_darwin)
626 /*--------------------------------------------------------------------*/
628 /*--------------------------------------------------------------------*/