Bug 439685 compiler warning in callgrind/main.c
[valgrind.git] / coregrind / m_initimg / initimg-darwin.c
blob564d2fdaa7eaf4ba46d28289eed6f64105d3ae8a
2 /*--------------------------------------------------------------------*/
3 /*--- Startup: create initial process image on Darwin ---*/
4 /*--- initimg-darwin.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2017 Julian Seward
12 jseward@acm.org
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;
63 Int ret;
64 SysRes res;
66 vg_assert( VG_(args_the_exename) != NULL);
67 exe_name = VG_(find_executable)( VG_(args_the_exename) );
69 if (!exe_name) {
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);
82 if (!sr_isError(res))
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
95 environment, except:
97 DYLD_INSERT_LIBRARIES=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
98 ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
99 DYLD_INSERT_LIBRARIES
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));
128 HChar** cpp;
129 HChar** ret;
130 HChar* preload_tool_path;
131 Int envc, i;
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
136 slop. */
137 Int preload_core_path_len = vglib_len + sizeof(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
145 preload_string. */
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);
152 } else {
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 */
162 envc = 0;
163 for (cpp = origenv; cpp && *cpp; cpp++)
164 envc++;
166 /* Allocate a new space */
167 ret = VG_(malloc) ("initimg-darwin.sce.3",
168 sizeof(HChar *) * (envc+2+1)); /* 2 new entries + NULL */
170 /* copy it over */
171 for (cpp = ret; *origenv; )
172 *cpp++ = *origenv++;
173 *cpp = NULL;
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);
186 *cpp = cp;
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);
196 *cpp = cp;
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);
209 ret[envc++] = cp;
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);
217 ret[envc++] = cp;
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))
225 break;
227 if (i < envc) {
228 for (; i < envc-1; i++)
229 ret[i] = ret[i+1];
230 envc--;
233 /* Change VYLD_ to DYLD */
234 for (i = 0; i < envc; i++) {
235 if (0 == VG_(strncmp)(ret[i], "VYLD_", 5)) {
236 ret[i][0] = 'D';
241 VG_(free)(preload_string);
242 ret[envc] = NULL;
243 return ret;
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)
254 HChar *cp = *tab;
255 HChar *orig = cp;
257 while(*str)
258 *cp++ = *str++;
259 *cp++ = '\0';
261 if (0)
262 VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
264 *tab = cp;
266 return 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
279 : string table :
281 +-----------------+
282 | NULL |
283 +-----------------+
284 | executable_path | (first arg to execve())
285 +-----------------+
286 | NULL |
288 | envp |
289 +-----------------+
290 | NULL |
292 | argv |
293 +-----------------+
294 | argc |
295 +-----------------+
296 | mach_header * | (dynamic only)
297 lower address +-----------------+ <- sp
298 | undefined |
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 ---------------------------------------------------------------- */
307 static
308 Addr setup_client_stack( void* init_sp,
309 HChar** orig_envp,
310 const ExeInfo* info,
311 Addr clstack_end,
312 SizeT clstack_max_size,
313 const VexArchInfo* vex_archinfo )
315 HChar **cpp;
316 HChar *strtab; /* string table */
317 HChar *stringbase;
318 Addr *ptr;
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) */
325 Addr clstack_start;
326 Int i;
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 */
334 stringsize = 0;
335 auxsize = 0;
337 /* paste on the extra args if the loader needs them (ie, the #!
338 interpreter and its argument) */
339 argc = 0;
340 if (info->interp_name != NULL) {
341 argc++;
342 stringsize += VG_(strlen)(info->interp_name) + 1;
344 if (info->interp_args != NULL) {
345 argc++;
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++) {
353 argc++;
354 stringsize += VG_(strlen)( * (HChar**)
355 VG_(indexXA)( VG_(args_for_client), i ))
356 + 1;
359 /* ...and the environment */
360 envc = 0;
361 for (cpp = orig_envp; cpp && *cpp; cpp++) {
362 envc++;
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 */
376 stacksize =
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 */
383 auxsize + /* auxv */
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;
407 if (0)
408 VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n"
409 "clstack_start %p\n"
410 "clstack_end %p\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(
438 &strtab,
439 * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
442 *ptr++ = 0;
444 /* --- envp --- */
445 VG_(client_envp) = (HChar **)ptr;
446 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
447 *ptr = (Addr)copy_str(&strtab, *cpp);
448 *ptr++ = 0;
450 /* --- executable_path + NULL --- */
451 if (info->executable_path)
452 *ptr++ = (Addr)copy_str(&strtab, info->executable_path);
453 else
454 *ptr++ = 0;
455 *ptr++ = 0;
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);
462 return 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
477 for rationale. */
478 return;
479 /*NOTREACHED*/
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);
494 #else
495 # error unknown architecture
496 #endif
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 )
508 ExeInfo info;
509 VG_(memset)( &info, 0, sizeof(info) );
511 HChar** env = NULL;
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,
547 vex_archinfo );
549 VG_(free)(env);
551 VG_(debugLog)(2, "initimg",
552 "Client info: "
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;
565 return iifii;
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
589 sane way. */
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
604 sane way. */
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;
615 # else
616 # error Unknown platform
617 # endif
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 /*--------------------------------------------------------------------*/
627 /*--- end ---*/
628 /*--------------------------------------------------------------------*/