Home | History | Annotate | Download | only in m_initimg
      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-2017 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_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 
     61 static 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 */
    116 static 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 */
    254 static 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 
    309 static
    310 Addr 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    if (info->interp_args)
    434       *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
    435 
    436    *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
    437 
    438    for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
    439       *ptr++ = (Addr)copy_str(
    440                        &strtab,
    441                        * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
    442                      );
    443    }
    444    *ptr++ = 0;
    445 
    446    /* --- envp --- */
    447    VG_(client_envp) = (HChar **)ptr;
    448    for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
    449       *ptr = (Addr)copy_str(&strtab, *cpp);
    450    *ptr++ = 0;
    451 
    452    /* --- executable_path + NULL --- */
    453    if (info->executable_path)
    454        *ptr++ = (Addr)copy_str(&strtab, info->executable_path);
    455    else
    456        *ptr++ = 0;
    457    *ptr++ = 0;
    458 
    459    vg_assert((strtab-stringbase) == stringsize);
    460 
    461    /* client_SP is pointing at client's argc/argv */
    462 
    463    if (0) VG_(printf)("startup SP = %#lx\n", client_SP);
    464    return client_SP;
    465 }
    466 
    467 
    468 /*====================================================================*/
    469 /*=== Record system memory regions                                 ===*/
    470 /*====================================================================*/
    471 
    472 static void record_system_memory(void)
    473 {
    474   /* JRS 2014-Jul-08: this messes up the sync checker, because the
    475      information that the kernel gives us doesn't include anything
    476      about the commpage mapping.  This functionality has therefore
    477      been moved to m_main.c, valgrind_main(), section "Tell the tool
    478      about the initial client memory permissions".  See comments there
    479      for rationale. */
    480    return;
    481    /*NOTREACHED*/
    482 
    483    /* Tell aspacem where the client's kernel commpage is */
    484 #if defined(VGA_amd64)
    485    /* commpage 0x7fff:ffe00000+ - not in vm_region */
    486    // GrP fixme check again
    487    VG_(am_notify_client_mmap)(0x7fffffe00000, 0x7ffffffff000-0x7fffffe00000,
    488                               VKI_PROT_READ|VKI_PROT_EXEC, 0, -1, 0);
    489 
    490 #elif defined(VGA_x86)
    491    /* commpage 0xfffec000+ - not in vm_region */
    492    // GrP fixme check again
    493    VG_(am_notify_client_mmap)(0xfffec000, 0xfffff000-0xfffec000,
    494                               VKI_PROT_READ|VKI_PROT_EXEC, 0, -1, 0);
    495 
    496 #else
    497 #  error unknown architecture
    498 #endif
    499 }
    500 
    501 
    502 /*====================================================================*/
    503 /*=== TOP-LEVEL: VG_(ii_create_image)                              ===*/
    504 /*====================================================================*/
    505 
    506 /* Create the client's initial memory image. */
    507 IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii,
    508                                           const VexArchInfo* vex_archinfo )
    509 {
    510    ExeInfo info;
    511    VG_(memset)( &info, 0, sizeof(info) );
    512 
    513    HChar** env = NULL;
    514 
    515    IIFinaliseImageInfo iifii;
    516    VG_(memset)( &iifii, 0, sizeof(iifii) );
    517 
    518    //--------------------------------------------------------------
    519    // Load client executable, finding in $PATH if necessary
    520    //   p: get_helprequest_and_toolname()  [for 'exec', 'need_help']
    521    //   p: layout_remaining_space          [so there's space]
    522    //--------------------------------------------------------------
    523    VG_(debugLog)(1, "initimg", "Loading client\n");
    524 
    525    if (VG_(args_the_exename) == NULL)
    526       VG_(err_missing_prog)();
    527 
    528    load_client(&info, &iifii.initial_client_IP);
    529 
    530    //--------------------------------------------------------------
    531    // Set up client's environment
    532    //   p: set-libdir                   [for VG_(libdir)]
    533    //   p: get_helprequest_and_toolname [for toolname]
    534    //--------------------------------------------------------------
    535    VG_(debugLog)(1, "initimg", "Setup client env\n");
    536    env = setup_client_env(iicii.envp, iicii.toolname);
    537 
    538    //--------------------------------------------------------------
    539    // Setup client stack, eip, and VG_(client_arg[cv])
    540    //   p: load_client()     [for 'info']
    541    //   p: fix_environment() [for 'env']
    542    //--------------------------------------------------------------
    543    iicii.clstack_end = info.stack_end;
    544    iifii.clstack_max_size = info.stack_end - info.stack_start + 1;
    545 
    546    iifii.initial_client_SP =
    547        setup_client_stack( iicii.argv - 1, env, &info,
    548                            iicii.clstack_end, iifii.clstack_max_size,
    549                            vex_archinfo );
    550 
    551    VG_(free)(env);
    552 
    553    VG_(debugLog)(2, "initimg",
    554                  "Client info: "
    555                  "initial_IP=%p initial_SP=%p stack=[%p..%p]\n",
    556                  (void*)(iifii.initial_client_IP),
    557                  (void*)(iifii.initial_client_SP),
    558                  (void*)(info.stack_start),
    559                  (void*)(info.stack_end));
    560 
    561 
    562    // Tell aspacem about commpage, etc
    563    record_system_memory();
    564 
    565    VG_(free)(info.interp_name); info.interp_name = NULL;
    566    VG_(free)(info.interp_args); info.interp_args = NULL;
    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