mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-12 06:11:37 +00:00
631 lines
21 KiB
C
631 lines
21 KiB
C
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- Startup: create initial process image on Darwin ---*/
|
|
/*--- initimg-darwin.c ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/*
|
|
This file is part of Valgrind, a dynamic binary instrumentation
|
|
framework.
|
|
|
|
Copyright (C) 2000-2012 Julian Seward
|
|
jseward@acm.org
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
02111-1307, USA.
|
|
|
|
The GNU General Public License is contained in the file COPYING.
|
|
*/
|
|
|
|
#if defined(VGO_darwin)
|
|
|
|
#include "pub_core_basics.h"
|
|
#include "pub_core_vki.h"
|
|
#include "pub_core_debuglog.h"
|
|
#include "pub_core_libcbase.h"
|
|
#include "pub_core_libcassert.h"
|
|
#include "pub_core_libcfile.h"
|
|
#include "pub_core_libcproc.h"
|
|
#include "pub_core_libcprint.h"
|
|
#include "pub_core_xarray.h"
|
|
#include "pub_core_clientstate.h"
|
|
#include "pub_core_aspacemgr.h"
|
|
#include "pub_core_mallocfree.h"
|
|
#include "pub_core_machine.h"
|
|
#include "pub_core_ume.h"
|
|
#include "pub_core_options.h"
|
|
#include "pub_core_tooliface.h" /* VG_TRACK */
|
|
#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
|
|
#include "pub_core_threadstate.h" /* ThreadArchState */
|
|
#include "priv_initimg_pathscan.h"
|
|
#include "pub_core_initimg.h" /* self */
|
|
|
|
|
|
/*====================================================================*/
|
|
/*=== Loading the client ===*/
|
|
/*====================================================================*/
|
|
|
|
/* Load the client whose name is VG_(argv_the_exename). */
|
|
|
|
static void load_client ( /*OUT*/ExeInfo* info,
|
|
/*OUT*/Addr* client_ip)
|
|
{
|
|
const HChar* exe_name;
|
|
Int ret;
|
|
SysRes res;
|
|
|
|
vg_assert( VG_(args_the_exename) != NULL);
|
|
exe_name = ML_(find_executable)( VG_(args_the_exename) );
|
|
|
|
if (!exe_name) {
|
|
VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
|
|
VG_(exit)(127); // 127 is Posix NOTFOUND
|
|
}
|
|
|
|
VG_(memset)(info, 0, sizeof(*info));
|
|
ret = VG_(do_exec)(exe_name, info);
|
|
|
|
// The client was successfully loaded! Continue.
|
|
|
|
/* Get hold of a file descriptor which refers to the client
|
|
executable. This is needed for attaching to GDB. */
|
|
res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
|
|
if (!sr_isError(res))
|
|
VG_(cl_exec_fd) = sr_Res(res);
|
|
|
|
/* Copy necessary bits of 'info' that were filled in */
|
|
*client_ip = info->init_ip;
|
|
}
|
|
|
|
|
|
/*====================================================================*/
|
|
/*=== Setting up the client's environment ===*/
|
|
/*====================================================================*/
|
|
|
|
/* Prepare the client's environment. This is basically a copy of our
|
|
environment, except:
|
|
|
|
DYLD_INSERT_LIBRARIES=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
|
|
($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
|
|
DYLD_INSERT_LIBRARIES
|
|
|
|
If this is missing, then it is added.
|
|
|
|
Also, remove any binding for VALGRIND_LAUNCHER=. The client should
|
|
not be able to see this.
|
|
|
|
Also, add DYLD_SHARED_REGION=avoid, because V doesn't know how
|
|
to process the dyld shared cache file.
|
|
|
|
Also, change VYLD_* (mangled by launcher) back to DYLD_*.
|
|
|
|
If this needs to handle any more variables it should be hacked
|
|
into something table driven. The copy is VG_(malloc)'d space.
|
|
*/
|
|
static HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
|
|
{
|
|
const HChar* preload_core = "vgpreload_core";
|
|
const HChar* ld_preload = "DYLD_INSERT_LIBRARIES=";
|
|
const HChar* dyld_cache = "DYLD_SHARED_REGION=";
|
|
const HChar* dyld_cache_value= "avoid";
|
|
const HChar* v_launcher = VALGRIND_LAUNCHER "=";
|
|
Int ld_preload_len = VG_(strlen)( ld_preload );
|
|
Int dyld_cache_len = VG_(strlen)( dyld_cache );
|
|
Int v_launcher_len = VG_(strlen)( v_launcher );
|
|
Bool ld_preload_done = False;
|
|
Bool dyld_cache_done = False;
|
|
Int vglib_len = VG_(strlen)(VG_(libdir));
|
|
|
|
HChar** cpp;
|
|
HChar** ret;
|
|
HChar* preload_tool_path;
|
|
Int envc, i;
|
|
|
|
/* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
|
|
paths. We might not need the space for vgpreload_<tool>.so, but it
|
|
doesn't hurt to over-allocate briefly. The 16s are just cautious
|
|
slop. */
|
|
Int preload_core_path_len = vglib_len + sizeof(preload_core)
|
|
+ sizeof(VG_PLATFORM) + 16;
|
|
Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname)
|
|
+ sizeof(VG_PLATFORM) + 16;
|
|
Int preload_string_len = preload_core_path_len + preload_tool_path_len;
|
|
HChar* preload_string = VG_(malloc)("initimg-darwin.sce.1", preload_string_len);
|
|
vg_assert(preload_string);
|
|
|
|
/* Determine if there's a vgpreload_<tool>_<platform>.so file, and setup
|
|
preload_string. */
|
|
preload_tool_path = VG_(malloc)("initimg-darwin.sce.2", preload_tool_path_len);
|
|
vg_assert(preload_tool_path);
|
|
VG_(snprintf)(preload_tool_path, preload_tool_path_len,
|
|
"%s/vgpreload_%s-%s.so", VG_(libdir), toolname, VG_PLATFORM);
|
|
if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
|
|
VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so:%s",
|
|
VG_(libdir), preload_core, VG_PLATFORM, preload_tool_path);
|
|
} else {
|
|
VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so",
|
|
VG_(libdir), preload_core, VG_PLATFORM);
|
|
}
|
|
VG_(free)(preload_tool_path);
|
|
|
|
VG_(debugLog)(2, "initimg", "preload_string:\n");
|
|
VG_(debugLog)(2, "initimg", " \"%s\"\n", preload_string);
|
|
|
|
/* Count the original size of the env */
|
|
envc = 0;
|
|
for (cpp = origenv; cpp && *cpp; cpp++)
|
|
envc++;
|
|
|
|
/* Allocate a new space */
|
|
ret = VG_(malloc) ("initimg-darwin.sce.3",
|
|
sizeof(HChar *) * (envc+2+1)); /* 2 new entries + NULL */
|
|
vg_assert(ret);
|
|
|
|
/* copy it over */
|
|
for (cpp = ret; *origenv; )
|
|
*cpp++ = *origenv++;
|
|
*cpp = NULL;
|
|
|
|
vg_assert(envc == (cpp - ret));
|
|
|
|
/* Walk over the new environment, mashing as we go */
|
|
for (cpp = ret; cpp && *cpp; cpp++) {
|
|
if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) {
|
|
Int len = VG_(strlen)(*cpp) + preload_string_len;
|
|
HChar *cp = VG_(malloc)("initimg-darwin.sce.4", len);
|
|
vg_assert(cp);
|
|
|
|
VG_(snprintf)(cp, len, "%s%s:%s",
|
|
ld_preload, preload_string, (*cpp)+ld_preload_len);
|
|
|
|
*cpp = cp;
|
|
|
|
ld_preload_done = True;
|
|
}
|
|
if (VG_(memcmp)(*cpp, dyld_cache, dyld_cache_len) == 0) {
|
|
Int len = dyld_cache_len + VG_(strlen)(dyld_cache_value) + 1;
|
|
HChar *cp = VG_(malloc)("initimg-darwin.sce.4.2", len);
|
|
vg_assert(cp);
|
|
|
|
VG_(snprintf)(cp, len, "%s%s", dyld_cache, dyld_cache_value);
|
|
|
|
*cpp = cp;
|
|
|
|
ld_preload_done = True;
|
|
}
|
|
}
|
|
|
|
/* Add the missing bits */
|
|
if (!ld_preload_done) {
|
|
Int len = ld_preload_len + preload_string_len;
|
|
HChar *cp = VG_(malloc) ("initimg-darwin.sce.5", len);
|
|
vg_assert(cp);
|
|
|
|
VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
|
|
|
|
ret[envc++] = cp;
|
|
}
|
|
if (!dyld_cache_done) {
|
|
Int len = dyld_cache_len + VG_(strlen)(dyld_cache_value) + 1;
|
|
HChar *cp = VG_(malloc) ("initimg-darwin.sce.5.2", len);
|
|
vg_assert(cp);
|
|
|
|
VG_(snprintf)(cp, len, "%s%s", dyld_cache, dyld_cache_value);
|
|
|
|
ret[envc++] = cp;
|
|
}
|
|
|
|
|
|
/* ret[0 .. envc-1] is live now. */
|
|
/* Find and remove a binding for VALGRIND_LAUNCHER. */
|
|
for (i = 0; i < envc; i++)
|
|
if (0 == VG_(memcmp)(ret[i], v_launcher, v_launcher_len))
|
|
break;
|
|
|
|
if (i < envc) {
|
|
for (; i < envc-1; i++)
|
|
ret[i] = ret[i+1];
|
|
envc--;
|
|
}
|
|
|
|
/* Change VYLD_ to DYLD */
|
|
for (i = 0; i < envc; i++) {
|
|
if (0 == VG_(strncmp)(ret[i], "VYLD_", 5)) {
|
|
ret[i][0] = 'D';
|
|
}
|
|
}
|
|
|
|
|
|
VG_(free)(preload_string);
|
|
ret[envc] = NULL;
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*====================================================================*/
|
|
/*=== Setting up the client's stack ===*/
|
|
/*====================================================================*/
|
|
|
|
/* Add a string onto the string table, and return its address */
|
|
static HChar *copy_str(HChar **tab, const HChar *str)
|
|
{
|
|
HChar *cp = *tab;
|
|
HChar *orig = cp;
|
|
|
|
while(*str)
|
|
*cp++ = *str++;
|
|
*cp++ = '\0';
|
|
|
|
if (0)
|
|
VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
|
|
|
|
*tab = cp;
|
|
|
|
return orig;
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
|
|
|
This sets up the client's initial stack, containing the args,
|
|
environment and aux vector.
|
|
|
|
The format of the stack on Darwin is:
|
|
|
|
higher address +-----------------+ <- clstack_end
|
|
| |
|
|
: string table :
|
|
| |
|
|
+-----------------+
|
|
| NULL |
|
|
+-----------------+
|
|
| executable_path | (first arg to execve())
|
|
+-----------------+
|
|
| NULL |
|
|
- -
|
|
| envp |
|
|
+-----------------+
|
|
| NULL |
|
|
- -
|
|
| argv |
|
|
+-----------------+
|
|
| argc |
|
|
+-----------------+
|
|
| mach_header * | (dynamic only)
|
|
lower address +-----------------+ <- sp
|
|
| undefined |
|
|
: :
|
|
|
|
Allocate and create the initial client stack. It is allocated down
|
|
from clstack_end, which was previously determined by the address
|
|
space manager. The returned value is the SP value for the client.
|
|
|
|
---------------------------------------------------------------- */
|
|
|
|
static
|
|
Addr setup_client_stack( void* init_sp,
|
|
HChar** orig_envp,
|
|
const ExeInfo* info,
|
|
Addr clstack_end,
|
|
SizeT clstack_max_size )
|
|
{
|
|
HChar **cpp;
|
|
HChar *strtab; /* string table */
|
|
HChar *stringbase;
|
|
Addr *ptr;
|
|
unsigned stringsize; /* total size of strings in bytes */
|
|
unsigned auxsize; /* total size of auxv in bytes */
|
|
Int argc; /* total argc */
|
|
Int envc; /* total number of env vars */
|
|
unsigned stacksize; /* total client stack size */
|
|
Addr client_SP; /* client stack base (initial SP) */
|
|
Addr clstack_start;
|
|
Int i;
|
|
Bool have_exename;
|
|
|
|
vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
|
|
vg_assert( VG_(args_for_client) );
|
|
|
|
/* ==================== compute sizes ==================== */
|
|
|
|
/* first of all, work out how big the client stack will be */
|
|
stringsize = 0;
|
|
auxsize = 0;
|
|
have_exename = VG_(args_the_exename) != NULL;
|
|
|
|
/* paste on the extra args if the loader needs them (ie, the #!
|
|
interpreter and its argument) */
|
|
argc = 0;
|
|
if (info->interp_name != NULL) {
|
|
argc++;
|
|
stringsize += VG_(strlen)(info->interp_name) + 1;
|
|
}
|
|
if (info->interp_args != NULL) {
|
|
argc++;
|
|
stringsize += VG_(strlen)(info->interp_args) + 1;
|
|
}
|
|
|
|
/* now scan the args we're given... */
|
|
if (have_exename)
|
|
stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
|
|
|
|
for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
|
|
argc++;
|
|
stringsize += VG_(strlen)( * (HChar**)
|
|
VG_(indexXA)( VG_(args_for_client), i ))
|
|
+ 1;
|
|
}
|
|
|
|
/* ...and the environment */
|
|
envc = 0;
|
|
for (cpp = orig_envp; cpp && *cpp; cpp++) {
|
|
envc++;
|
|
stringsize += VG_(strlen)(*cpp) + 1;
|
|
}
|
|
|
|
/* Darwin executable_path + NULL */
|
|
auxsize += 2 * sizeof(Word);
|
|
if (info->executable_path) {
|
|
stringsize += 1 + VG_(strlen)(info->executable_path);
|
|
}
|
|
|
|
/* Darwin mach_header */
|
|
if (info->dynamic) auxsize += sizeof(Word);
|
|
|
|
/* OK, now we know how big the client stack is */
|
|
stacksize =
|
|
sizeof(Word) + /* argc */
|
|
(have_exename ? sizeof(HChar **) : 0) + /* argc[0] == exename */
|
|
sizeof(HChar **)*argc + /* argv */
|
|
sizeof(HChar **) + /* terminal NULL */
|
|
sizeof(HChar **)*envc + /* envp */
|
|
sizeof(HChar **) + /* terminal NULL */
|
|
auxsize + /* auxv */
|
|
VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */
|
|
|
|
if (0) VG_(printf)("stacksize = %d\n", stacksize);
|
|
|
|
/* client_SP is the client's stack pointer */
|
|
client_SP = clstack_end - stacksize;
|
|
client_SP = VG_ROUNDDN(client_SP, 32); /* make stack 32 byte aligned */
|
|
|
|
/* base of the string table (aligned) */
|
|
stringbase = strtab = (HChar *)clstack_end
|
|
- VG_ROUNDUP(stringsize, sizeof(int));
|
|
|
|
/* The max stack size */
|
|
clstack_max_size = VG_PGROUNDUP(clstack_max_size);
|
|
|
|
/* Darwin stack is chosen by the ume loader */
|
|
clstack_start = clstack_end - clstack_max_size;
|
|
|
|
/* Record stack extent -- needed for stack-change code. */
|
|
/* GrP fixme really? */
|
|
VG_(clstk_base) = clstack_start;
|
|
VG_(clstk_end) = clstack_end;
|
|
|
|
if (0)
|
|
VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n"
|
|
"clstack_start %p\n"
|
|
"clstack_end %p\n",
|
|
stringsize, auxsize, stacksize, (Int)clstack_max_size,
|
|
(void*)clstack_start, (void*)clstack_end);
|
|
|
|
/* ==================== allocate space ==================== */
|
|
|
|
/* Stack was allocated by the ume loader. */
|
|
|
|
/* ==================== create client stack ==================== */
|
|
|
|
ptr = (Addr*)client_SP;
|
|
|
|
/* --- mach_header --- */
|
|
if (info->dynamic) *ptr++ = info->text;
|
|
|
|
/* --- client argc --- */
|
|
*ptr++ = (Addr)(argc + (have_exename ? 1 : 0));
|
|
|
|
/* --- client argv --- */
|
|
if (info->interp_name) {
|
|
*ptr++ = (Addr)copy_str(&strtab, info->interp_name);
|
|
VG_(free)(info->interp_name);
|
|
}
|
|
if (info->interp_args) {
|
|
*ptr++ = (Addr)copy_str(&strtab, info->interp_args);
|
|
VG_(free)(info->interp_args);
|
|
}
|
|
|
|
if (have_exename)
|
|
*ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
|
|
|
|
for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
|
|
*ptr++ = (Addr)copy_str(
|
|
&strtab,
|
|
* (HChar**) VG_(indexXA)( VG_(args_for_client), i )
|
|
);
|
|
}
|
|
*ptr++ = 0;
|
|
|
|
/* --- envp --- */
|
|
VG_(client_envp) = (HChar **)ptr;
|
|
for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
|
|
*ptr = (Addr)copy_str(&strtab, *cpp);
|
|
*ptr++ = 0;
|
|
|
|
/* --- executable_path + NULL --- */
|
|
if (info->executable_path)
|
|
*ptr++ = (Addr)copy_str(&strtab, info->executable_path);
|
|
else
|
|
*ptr++ = 0;
|
|
*ptr++ = 0;
|
|
|
|
vg_assert((strtab-stringbase) == stringsize);
|
|
|
|
/* client_SP is pointing at client's argc/argv */
|
|
|
|
if (0) VG_(printf)("startup SP = %#lx\n", client_SP);
|
|
return client_SP;
|
|
}
|
|
|
|
|
|
/*====================================================================*/
|
|
/*=== Record system memory regions ===*/
|
|
/*====================================================================*/
|
|
|
|
static void record_system_memory(void)
|
|
{
|
|
/* Tell aspacem where the client's kernel commpage is */
|
|
#if defined(VGA_amd64)
|
|
/* commpage 0x7fff:ffe00000+ - not in vm_region */
|
|
// GrP fixme check again
|
|
VG_(am_notify_client_mmap)(0x7fffffe00000, 0x7ffffffff000-0x7fffffe00000,
|
|
VKI_PROT_READ|VKI_PROT_EXEC, 0, -1, 0);
|
|
|
|
#elif defined(VGA_x86)
|
|
/* commpage 0xfffec000+ - not in vm_region */
|
|
// GrP fixme check again
|
|
VG_(am_notify_client_mmap)(0xfffec000, 0xfffff000-0xfffec000,
|
|
VKI_PROT_READ|VKI_PROT_EXEC, 0, -1, 0);
|
|
|
|
#else
|
|
# error unknown architecture
|
|
#endif
|
|
}
|
|
|
|
|
|
/*====================================================================*/
|
|
/*=== TOP-LEVEL: VG_(ii_create_image) ===*/
|
|
/*====================================================================*/
|
|
|
|
/* Create the client's initial memory image. */
|
|
IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii )
|
|
{
|
|
ExeInfo info;
|
|
HChar** env = NULL;
|
|
|
|
IIFinaliseImageInfo iifii;
|
|
VG_(memset)( &iifii, 0, sizeof(iifii) );
|
|
|
|
//--------------------------------------------------------------
|
|
// Load client executable, finding in $PATH if necessary
|
|
// p: get_helprequest_and_toolname() [for 'exec', 'need_help']
|
|
// p: layout_remaining_space [so there's space]
|
|
//--------------------------------------------------------------
|
|
VG_(debugLog)(1, "initimg", "Loading client\n");
|
|
|
|
if (VG_(args_the_exename) == NULL)
|
|
VG_(err_missing_prog)();
|
|
|
|
load_client(&info, &iifii.initial_client_IP);
|
|
|
|
//--------------------------------------------------------------
|
|
// Set up client's environment
|
|
// p: set-libdir [for VG_(libdir)]
|
|
// p: get_helprequest_and_toolname [for toolname]
|
|
//--------------------------------------------------------------
|
|
VG_(debugLog)(1, "initimg", "Setup client env\n");
|
|
env = setup_client_env(iicii.envp, iicii.toolname);
|
|
|
|
//--------------------------------------------------------------
|
|
// Setup client stack, eip, and VG_(client_arg[cv])
|
|
// p: load_client() [for 'info']
|
|
// p: fix_environment() [for 'env']
|
|
//--------------------------------------------------------------
|
|
iicii.clstack_top = info.stack_end - 1;
|
|
iifii.clstack_max_size = info.stack_end - info.stack_start;
|
|
|
|
iifii.initial_client_SP =
|
|
setup_client_stack( iicii.argv - 1, env, &info,
|
|
iicii.clstack_top, iifii.clstack_max_size );
|
|
|
|
VG_(free)(env);
|
|
|
|
VG_(debugLog)(2, "initimg",
|
|
"Client info: "
|
|
"initial_IP=%p initial_SP=%p stack=%p..%p\n",
|
|
(void*)(iifii.initial_client_IP),
|
|
(void*)(iifii.initial_client_SP),
|
|
(void*)(info.stack_start),
|
|
(void*)(info.stack_end));
|
|
|
|
|
|
// Tell aspacem about commpage, etc
|
|
record_system_memory();
|
|
|
|
return iifii;
|
|
}
|
|
|
|
|
|
/*====================================================================*/
|
|
/*=== TOP-LEVEL: VG_(ii_finalise_image) ===*/
|
|
/*====================================================================*/
|
|
|
|
/* Just before starting the client, we may need to make final
|
|
adjustments to its initial image. Also we need to set up the VEX
|
|
guest state for thread 1 (the root thread) and copy in essential
|
|
starting values. This is handed the IIFinaliseImageInfo created by
|
|
VG_(ii_create_image).
|
|
*/
|
|
void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
|
|
{
|
|
ThreadArchState* arch = &VG_(threads)[1].arch;
|
|
|
|
/* GrP fixme doesn't handle all registers from LC_THREAD or LC_UNIXTHREAD */
|
|
|
|
# if defined(VGP_x86_darwin)
|
|
vg_assert(0 == sizeof(VexGuestX86State) % 16);
|
|
|
|
/* Zero out the initial state, and set up the simulated FPU in a
|
|
sane way. */
|
|
LibVEX_GuestX86_initialise(&arch->vex);
|
|
|
|
/* Zero out the shadow areas. */
|
|
VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State));
|
|
VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State));
|
|
|
|
/* Put essential stuff into the new state. */
|
|
arch->vex.guest_ESP = iifii.initial_client_SP;
|
|
arch->vex.guest_EIP = iifii.initial_client_IP;
|
|
|
|
# elif defined(VGP_amd64_darwin)
|
|
vg_assert(0 == sizeof(VexGuestAMD64State) % 16);
|
|
|
|
/* Zero out the initial state, and set up the simulated FPU in a
|
|
sane way. */
|
|
LibVEX_GuestAMD64_initialise(&arch->vex);
|
|
|
|
/* Zero out the shadow areas. */
|
|
VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State));
|
|
VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State));
|
|
|
|
/* Put essential stuff into the new state. */
|
|
arch->vex.guest_RSP = iifii.initial_client_SP;
|
|
arch->vex.guest_RIP = iifii.initial_client_IP;
|
|
|
|
# else
|
|
# error Unknown platform
|
|
# endif
|
|
|
|
/* Tell the tool that we just wrote to the registers. */
|
|
VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
|
|
sizeof(VexGuestArchState));
|
|
}
|
|
|
|
#endif // defined(VGO_darwin)
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- end ---*/
|
|
/*--------------------------------------------------------------------*/
|