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-2013 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       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 
    476 static 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. */
    511 IIFinaliseImageInfo 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 */
    583 void 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