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