initimg-linux.c revision 663860b1408516d02ebfcb3a9999a134e6cfb223
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Startup: create initial process image on Linux ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- initimg-linux.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2000-2012 Julian Seward 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcfile.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_ume.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" /* VG_TRACK */ 51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" /* ThreadArchState */ 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_initimg_pathscan.h" 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_initimg.h" /* self */ 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _FILE_OFFSET_BITS 64 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is for ELF types etc, and also the AT_ constants. */ 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <elf.h> 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== Loading the client ===*/ 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Load the client whose name is VG_(argv_the_exename). */ 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void load_client ( /*OUT*/ExeInfo* info, 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Addr* client_ip, 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Addr* client_toc) 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* exe_name; 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ret; 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(args_the_exename) != NULL); 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exe_name = ML_(find_executable)( VG_(args_the_exename) ); 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!exe_name) { 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename)); 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(127); // 127 is Posix NOTFOUND 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(info, 0, sizeof(*info)); 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(do_exec)(exe_name, info); 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret < 0) { 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("valgrind: could not execute '%s'\n", exe_name); 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The client was successfully loaded! Continue. 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get hold of a file descriptor which refers to the client 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executable. This is needed for attaching to GDB. */ 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(cl_exec_fd) = sr_Res(res); 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy necessary bits of 'info' that were filled in */ 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *client_ip = info->init_ip; 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *client_toc = info->init_toc; 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase); 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== Setting up the client's environment ===*/ 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Prepare the client's environment. This is basically a copy of our 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown environment, except: 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LD_PRELOAD=$VALGRIND_LIB/vgpreload_core-PLATFORM.so: 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)? 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown $LD_PRELOAD 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If this is missing, then it is added. 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Also, remove any binding for VALGRIND_LAUNCHER=. The client should 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not be able to see this. 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If this needs to handle any more variables it should be hacked 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown into something table driven. The copy is VG_(malloc)'d space. 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar** setup_client_env ( HChar** origenv, const HChar* toolname) 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* preload_core = "vgpreload_core"; 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* ld_preload = "LD_PRELOAD="; 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* v_launcher = VALGRIND_LAUNCHER "="; 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ld_preload_len = VG_(strlen)( ld_preload ); 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int v_launcher_len = VG_(strlen)( v_launcher ); 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ld_preload_done = False; 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int vglib_len = VG_(strlen)(VG_(libdir)); 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debug = False; 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar** cpp; 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar** ret; 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* preload_tool_path; 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int envc, i; 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown paths. We might not need the space for vgpreload_<tool>.so, but it 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doesn't hurt to over-allocate briefly. The 16s are just cautious 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown slop. */ 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int preload_core_path_len = vglib_len + sizeof(preload_core) 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + sizeof(VG_PLATFORM) + 16; 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + sizeof(VG_PLATFORM) + 16; 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int preload_string_len = preload_core_path_len + preload_tool_path_len; 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* preload_string = VG_(malloc)("initimg-linux.sce.1", 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preload_string_len); 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(origenv); 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(toolname); 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(preload_string); 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Determine if there's a vgpreload_<tool>_<platform>.so file, and setup 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preload_string. */ 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preload_tool_path = VG_(malloc)("initimg-linux.sce.2", preload_tool_path_len); 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(preload_tool_path); 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(snprintf)(preload_tool_path, preload_tool_path_len, 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s/vgpreload_%s-%s.so", VG_(libdir), toolname, VG_PLATFORM); 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) { 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so:%s", 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(libdir), preload_core, VG_PLATFORM, preload_tool_path); 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so", 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(libdir), preload_core, VG_PLATFORM); 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(preload_tool_path); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "initimg", "preload_string:\n"); 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "initimg", " \"%s\"\n", preload_string); 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count the original size of the env */ 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) VG_(printf)("\n\n"); 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envc = 0; 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = origenv; cpp && *cpp; cpp++) { 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envc++; 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) VG_(printf)("XXXXXXXXX: BEFORE %s\n", *cpp); 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Allocate a new space */ 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(malloc) ("initimg-linux.sce.3", 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(HChar *) * (envc+1+1)); /* 1 new entry + NULL */ 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret); 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* copy it over */ 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = ret; *origenv; ) { 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) VG_(printf)("XXXXXXXXX: COPY %s\n", *origenv); 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cpp++ = *origenv++; 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cpp = NULL; 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(envc == (cpp - ret)); 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Walk over the new environment, mashing as we go */ 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = ret; cpp && *cpp; cpp++) { 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) { 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len = VG_(strlen)(*cpp) + preload_string_len; 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar *cp = VG_(malloc)("initimg-linux.sce.4", len); 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(cp); 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(snprintf)(cp, len, "%s%s:%s", 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ld_preload, preload_string, (*cpp)+ld_preload_len); 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cpp = cp; 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ld_preload_done = True; 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) VG_(printf)("XXXXXXXXX: MASH %s\n", *cpp); 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Add the missing bits */ 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ld_preload_done) { 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len = ld_preload_len + preload_string_len; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar *cp = VG_(malloc) ("initimg-linux.sce.5", len); 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(cp); 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string); 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret[envc++] = cp; 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) VG_(printf)("XXXXXXXXX: ADD %s\n", cp); 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ret[0 .. envc-1] is live now. */ 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Find and remove a binding for VALGRIND_LAUNCHER. */ 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < envc; i++) 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(memcmp(ret[i], v_launcher, v_launcher_len))) 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i < envc) { 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (; i < envc-1; i++) 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret[i] = ret[i+1]; 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envc--; 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(preload_string); 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret[envc] = NULL; 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < envc; i++) { 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) VG_(printf)("XXXXXXXXX: FINAL %s\n", ret[i]); 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== Setting up the client's stack ===*/ 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_DCACHEBSIZE 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_DCACHEBSIZE 19 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_DCACHEBSIZE */ 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_ICACHEBSIZE 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_ICACHEBSIZE 20 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_ICACHEBSIZE */ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_UCACHEBSIZE 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_UCACHEBSIZE 21 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_UCACHEBSIZE */ 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_BASE_PLATFORM 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_BASE_PLATFORM 24 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_BASE_PLATFORM */ 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_RANDOM 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_RANDOM 25 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_RANDOM */ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_EXECFN 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_EXECFN 31 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_EXECFN */ 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_SYSINFO 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_SYSINFO 32 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_SYSINFO */ 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_SYSINFO_EHDR 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_SYSINFO_EHDR 33 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_SYSINFO_EHDR */ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef AT_SECURE 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_SECURE 23 /* secure mode boolean */ 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* AT_SECURE */ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a string onto the string table, and return its address */ 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *copy_str(char **tab, const char *str) 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *cp = *tab; 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *orig = cp; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(*str) 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cp++ = *str++; 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cp++ = '\0'; 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig)); 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *tab = cp; 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return orig; 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------- 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This sets up the client's initial stack, containing the args, 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown environment and aux vector. 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The format of the stack is: 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown higher address +-----------------+ <- clstack_end 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | | 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : string table : 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | | 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown +-----------------+ 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | AT_NULL | 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - - 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | auxv | 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown +-----------------+ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | NULL | 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - - 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | envp | 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown +-----------------+ 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | NULL | 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - - 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | argv | 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown +-----------------+ 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | argc | 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lower address +-----------------+ <- sp 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | undefined | 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : : 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Allocate and create the initial client stack. It is allocated down 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from clstack_end, which was previously determined by the address 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown space manager. The returned value is the SP value for the client. 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The client's auxv is created by copying and modifying our own one. 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown As a side effect of scanning our own auxv, some important bits of 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info are collected: 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(cache_line_size_ppc32) // ppc32 only -- cache line size 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(have_altivec_ppc32) // ppc32 only -- is Altivec supported? 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ---------------------------------------------------------------- */ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct auxv 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word a_type; 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union { 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *a_ptr; 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word a_val; 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } u; 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct auxv *find_auxv(UWord* sp) 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp++; // skip argc (Nb: is word-sized, not int-sized!) 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*sp != 0) // skip argv 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp++; 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp++; 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*sp != 0) // skip env 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp++; 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp++; 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGA_ppc32) || defined(VGA_ppc64) 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined AT_IGNOREPPC 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*sp == AT_IGNOREPPC) // skip AT_IGNOREPPC entries 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp += 2; 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (struct auxv *)sp; 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr setup_client_stack( void* init_sp, 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char** orig_envp, 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const ExeInfo* info, 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt** client_auxv, 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr clstack_end, 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT clstack_max_size ) 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char **cpp; 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *strtab; /* string table */ 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *stringbase; 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr *ptr; 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct auxv *auxv; 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct auxv *orig_auxv; 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct auxv *cauxv; 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned stringsize; /* total size of strings in bytes */ 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned auxsize; /* total size of auxv in bytes */ 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int argc; /* total argc */ 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int envc; /* total number of env vars */ 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned stacksize; /* total client stack size */ 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr client_SP; /* client stack base (initial SP) */ 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr clstack_start; 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool have_exename; 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1)); 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(args_for_client) ); 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* use our own auxv as a prototype */ 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown orig_auxv = find_auxv(init_sp); 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ==================== compute sizes ==================== */ 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first of all, work out how big the client stack will be */ 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize = 0; 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have_exename = VG_(args_the_exename) != NULL; 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* paste on the extra args if the loader needs them (ie, the #! 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interpreter and its argument) */ 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argc = 0; 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->interp_name != NULL) { 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argc++; 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize += VG_(strlen)(info->interp_name) + 1; 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->interp_args != NULL) { 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argc++; 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize += VG_(strlen)(info->interp_args) + 1; 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* now scan the args we're given... */ 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (have_exename) 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1; 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argc++; 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize += VG_(strlen)( * (HChar**) 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(indexXA)( VG_(args_for_client), i )) 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + 1; 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ...and the environment */ 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envc = 0; 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = orig_envp; cpp && *cpp; cpp++) { 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envc++; 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize += VG_(strlen)(*cpp) + 1; 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* now, how big is the auxv? */ 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */ 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) { 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cauxv->a_type == AT_PLATFORM || 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cauxv->a_type == AT_BASE_PLATFORM) 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize += VG_(strlen)(cauxv->u.a_ptr) + 1; 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (cauxv->a_type == AT_RANDOM) 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize += 16; 459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else if (cauxv->a_type == AT_EXECFN && have_exename) 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize += VG_(strlen)(VG_(args_the_exename)) + 1; 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxsize += sizeof(*cauxv); 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxsize += 2 * sizeof(*cauxv); 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* OK, now we know how big the client stack is */ 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stacksize = 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(Word) + /* argc */ 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (have_exename ? sizeof(char **) : 0) + /* argc[0] == exename */ 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(char **)*argc + /* argv */ 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(char **) + /* terminal NULL */ 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(char **)*envc + /* envp */ 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(char **) + /* terminal NULL */ 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxsize + /* auxv */ 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */ 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("stacksize = %d\n", stacksize); 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* client_SP is the client's stack pointer */ 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client_SP = clstack_end - stacksize; 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */ 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* base of the string table (aligned) */ 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringbase = strtab = (char *)clstack_end 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - VG_ROUNDUP(stringsize, sizeof(int)); 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clstack_start = VG_PGROUNDDN(client_SP); 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The max stack size */ 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clstack_max_size = VG_PGROUNDUP(clstack_max_size); 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Record stack extent -- needed for stack-change code. */ 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clstk_base) = clstack_start; 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clstk_end) = clstack_end; 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n" 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "clstack_start %p\n" 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "clstack_end %p\n", 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stringsize, auxsize, stacksize, (Int)clstack_max_size, 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)clstack_start, (void*)clstack_end); 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ==================== allocate space ==================== */ 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { SizeT anon_size = clstack_end - clstack_start + 1; 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT resvn_size = clstack_max_size - anon_size; 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr anon_start = clstack_start; 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr resvn_start = anon_start - resvn_size; 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT inner_HACK = 0; 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* So far we've only accounted for space requirements down to the 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack pointer. If this target's ABI requires a redzone below 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the stack pointer, we need to allocate an extra page, to 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle the worst case in which the stack pointer is almost at 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the bottom of a page, and so there is insufficient room left 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown over to put the redzone in. In this case the simple thing to 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do is allocate an extra page, by shrinking the reservation by 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown one page and growing the anonymous area by a corresponding 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown page. */ 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_STACK_REDZONE_SZB >= 0); 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE); 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_STACK_REDZONE_SZB > 0) { 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(resvn_size > VKI_PAGE_SIZE); 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_size -= VKI_PAGE_SIZE; 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_start -= VKI_PAGE_SIZE; 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_size += VKI_PAGE_SIZE; 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(anon_size)); 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(resvn_size)); 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(anon_start)); 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(resvn_start)); 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(resvn_start == clstack_end + 1 - clstack_max_size); 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef ENABLE_INNER 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inner_HACK = 1024*1024; // create 1M non-fault-extending stack 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%#lx 0x%lx %#lx 0x%lx\n", 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_start, resvn_size, anon_start, anon_size); 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create a shrinkable reservation followed by an anonymous 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment. Together these constitute a growdown stack. */ 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(mk_SysRes_Error)(0); 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(am_create_reservation)( 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_start, 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_size -inner_HACK, 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SmUpper, 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_size +inner_HACK 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* allocate a stack - mmap enough space for the stack */ 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(am_mmap_anon_fixed_client)( 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_start -inner_HACK, 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_size +inner_HACK, 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((!ok) || sr_isError(res)) { 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Allocation of the stack failed. We have to stop. */ 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("valgrind: " 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "I failed to allocate space for the application's stack.\n"); 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("valgrind: " 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "This may be the result of a very large --main-stacksize=\n"); 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("valgrind: setting. Cannot continue. Sorry.\n\n"); 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(0); 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ok); 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sr_isError(res)); 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ==================== create client stack ==================== */ 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ptr = (Addr*)client_SP; 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- client argc --- */ 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ptr++ = argc + (have_exename ? 1 : 0); 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- client argv --- */ 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->interp_name) { 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ptr++ = (Addr)copy_str(&strtab, info->interp_name); 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(info->interp_name); 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->interp_args) { 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ptr++ = (Addr)copy_str(&strtab, info->interp_args); 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(info->interp_args); 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (have_exename) 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename)); 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ptr++ = (Addr)copy_str( 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &strtab, 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * (HChar**) VG_(indexXA)( VG_(args_for_client), i ) 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ptr++ = 0; 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- envp --- */ 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client_envp) = (Char **)ptr; 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++) 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ptr = (Addr)copy_str(&strtab, *cpp); 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ptr++ = 0; 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- auxv --- */ 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv = (struct auxv *)ptr; 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *client_auxv = (UInt *)auxv; 614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(client_auxv) = (UWord *)*client_auxv; 615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // ??? According to 'man proc', auxv is a array of unsigned long 616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // terminated by two zeros. Why is valgrind working with UInt ? 617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // We do not take ULong* (as ULong 8 bytes on a 32 bits), 618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // => we take UWord* 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv[0].a_type = AT_IGNOREPPC; 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv[0].u.a_val = AT_IGNOREPPC; 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv[1].a_type = AT_IGNOREPPC; 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv[1].u.a_val = AT_IGNOREPPC; 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv += 2; 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) { 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* copy the entry... */ 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *auxv = *orig_auxv; 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ...and fix up / examine the copy */ 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(auxv->a_type) { 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_IGNORE: 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_PHENT: 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_PAGESZ: 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_FLAGS: 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_NOTELF: 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_UID: 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_EUID: 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_GID: 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_EGID: 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_CLKTCK: 646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) 647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case AT_FPUCW: /* missing on android */ 648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All these are pointerless, so we don't need to do 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anything about them. */ 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_PHDR: 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->phdr == 0) 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->a_type = AT_IGNORE; 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->u.a_val = info->phdr; 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_PHNUM: 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (info->phdr == 0) 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->a_type = AT_IGNORE; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->u.a_val = info->phnum; 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_BASE: 668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* When gdbserver sends the auxv to gdb, the AT_BASE has 669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to be ignored, as otherwise gdb adds this offset 670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to loaded shared libs, causing wrong address 671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng relocation e.g. when inserting breaks. 672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng However, ignoring AT_BASE makes V crash on Android 4.1. 673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng So, keep the AT_BASE on android for now. 674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ??? Need to dig in depth about AT_BASE/GDB interaction */ 675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGPV_arm_linux_android) 676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov auxv->a_type = AT_IGNORE; 677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->u.a_val = info->interp_base; 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_PLATFORM: 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_BASE_PLATFORM: 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* points to a platform description string */ 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr); 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_ENTRY: 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->u.a_val = info->entry; 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_HWCAP: 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_arm_linux) 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Bool has_neon = (auxv->u.a_val & VKI_HWCAP_NEON) > 0; 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "initimg", 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ARM has-neon from-auxv: %s\n", 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown has_neon ? "YES" : "NO"); 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(machine_arm_set_has_NEON)( has_neon ); 698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng #define VKI_HWCAP_TLS 32768 699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool has_tls = (auxv->u.a_val & VKI_HWCAP_TLS) > 0; 700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(debugLog)(2, "initimg", 701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "ARM has-tls from-auxv: %s\n", 702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng has_tls ? "YES" : "NO"); 703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* If real hw sets properly HWCAP_TLS, we might 704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng use this info to decide to really execute set_tls syscall 705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng in syswrap-arm-linux.c rather than to base this on 706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng conditional compilation. */ 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_DCACHEBSIZE: 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_ICACHEBSIZE: 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_UCACHEBSIZE: 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_ppc32_linux) 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* acquire cache info */ 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (auxv->u.a_val > 0) { 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(machine_ppc32_set_clszB)( auxv->u.a_val ); 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "initimg", 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "PPC32 cache line size %u (type %u)\n", 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UInt)auxv->u.a_val, (UInt)auxv->a_type ); 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_linux) 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* acquire cache info */ 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (auxv->u.a_val > 0) { 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(machine_ppc64_set_clszB)( auxv->u.a_val ); 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "initimg", 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "PPC64 cache line size %u (type %u)\n", 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UInt)auxv->u.a_val, (UInt)auxv->a_type ); 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_IGNOREPPC: 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_SECURE: 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this is 1, then it means that this program is 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown running suid, and therefore the dynamic linker should 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be careful about LD_PRELOAD, etc. However, since 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stage1 (the thing the kernel actually execve's) should 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown never be SUID, and we need LD_PRELOAD to work for the 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client, we set AT_SECURE to 0. */ 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->u.a_val = 0; 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_SYSINFO: 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Trash this, because we don't reproduce it */ 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->a_type = AT_IGNORE; 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if !defined(VGP_ppc32_linux) && !defined(VGP_ppc64_linux) 754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case AT_SYSINFO_EHDR: { 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Trash this, because we don't reproduce it */ 756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const NSegment* ehdrseg = VG_(am_find_nsegment)((Addr)auxv->u.a_ptr); 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ehdrseg); 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_munmap_valgrind)(ehdrseg->start, ehdrseg->end - ehdrseg->start); 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->a_type = AT_IGNORE; 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_RANDOM: 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* points to 16 random bytes - we need to ensure this is 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown propagated to the client as glibc will assume it is 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown present if it is built for kernel 2.6.29 or later */ 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->u.a_ptr = strtab; 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memcpy)(strtab, orig_auxv->u.a_ptr, 16); 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown strtab += 16; 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case AT_EXECFN: 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* points to the executable filename */ 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->u.a_ptr = copy_str(&strtab, VG_(args_the_exename)); 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stomp out anything we don't know about */ 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "initimg", 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "stomping auxv entry %lld\n", 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)auxv->a_type); 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown auxv->a_type = AT_IGNORE; 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *auxv = *orig_auxv; 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(auxv->a_type == AT_NULL); 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert((strtab-stringbase) == stringsize); 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* client_SP is pointing at client's argc/argv */ 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("startup SP = %#lx\n", client_SP); 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return client_SP; 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Allocate the client data segment. It is an expandable anonymous 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mapping abutting a shrinkable reservation of size max_dseg_size. 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The data segment starts at VG_(brk_base), which is page-aligned, 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and runs up to VG_(brk_limit), which isn't. */ 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setup_client_dataseg ( SizeT max_size ) 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr anon_start = VG_(brk_base); 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT anon_size = VKI_PAGE_SIZE; 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr resvn_start = anon_start + anon_size; 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT resvn_size = max_size - anon_size; 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(anon_size)); 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(resvn_size)); 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(anon_start)); 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(resvn_start)); 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Because there's been no brk activity yet: */ 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(brk_base) == VG_(brk_limit)); 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try to create the data seg and associated reservation where 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(brk_base) says. */ 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(am_create_reservation)( 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_start, 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_size, 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SmLower, 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_size 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) { 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Hmm, that didn't work. Well, let aspacem suggest an address 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it likes better, and try again with that. */ 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_start = VG_(am_get_advisory_client_simple) 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( 0/*floating*/, anon_size+resvn_size, &ok ); 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_start = anon_start + anon_size; 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(am_create_reservation)( 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_start, 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resvn_size, 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SmLower, 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_size 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(brk_base) = VG_(brk_limit) = anon_start; 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* that too might have failed, but if it has, we're hosed: there 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is no Plan C. */ 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ok); 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We make the data segment (heap) executable because LinuxThreads on 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppc32 creates trampolines in this area. Also, on x86/Linux the data 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment is RWX natively, at least according to /proc/self/maps. 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Also, having a non-executable data seg would kill any program which 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tried to create code in the data seg and then run it. */ 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(am_mmap_anon_fixed_client)( 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_start, 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anon_size, 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sr_isError(sres)); 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sr_Res(sres) == anon_start); 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== TOP-LEVEL: VG_(setup_client_initial_image) ===*/ 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create the client's initial memory image. */ 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii ) 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeInfo info; 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar** env = NULL; 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IIFinaliseImageInfo iifii; 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)( &iifii, 0, sizeof(iifii) ); 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //-------------------------------------------------------------- 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Load client executable, finding in $PATH if necessary 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // p: get_helprequest_and_toolname() [for 'exec', 'need_help'] 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // p: layout_remaining_space [so there's space] 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //-------------------------------------------------------------- 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "initimg", "Loading client\n"); 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(args_the_exename) == NULL) 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(err_missing_prog)(); 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown load_client(&info, &iifii.initial_client_IP, &iifii.initial_client_TOC); 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //-------------------------------------------------------------- 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set up client's environment 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // p: set-libdir [for VG_(libdir)] 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // p: get_helprequest_and_toolname [for toolname] 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //-------------------------------------------------------------- 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "initimg", "Setup client env\n"); 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env = setup_client_env(iicii.envp, iicii.toolname); 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //-------------------------------------------------------------- 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Setup client stack, eip, and VG_(client_arg[cv]) 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // p: load_client() [for 'info'] 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // p: fix_environment() [for 'env'] 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //-------------------------------------------------------------- 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* When allocating space for the client stack on Linux, take 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notice of the --main-stacksize value. This makes it possible 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to run programs with very large (primary) stack requirements 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simply by specifying --main-stacksize. */ 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Logic is as follows: 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - by default, use the client's current stack rlimit 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if that exceeds 16M, clamp to 16M 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if a larger --main-stacksize value is specified, use that instead 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - in all situations, the minimum allowed stack size is 1M 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* init_sp = iicii.argv - 1; 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT m1 = 1024 * 1024; 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT m16 = 16 * m1; 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT szB = (SizeT)VG_(client_rlimit_stack).rlim_cur; 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (szB < m1) szB = m1; 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (szB > m16) szB = m16; 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_main_stacksize) > 0) szB = VG_(clo_main_stacksize); 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (szB < m1) szB = m1; 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown szB = VG_PGROUNDUP(szB); 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "initimg", 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Setup client stack: size will be %ld\n", szB); 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iifii.clstack_max_size = szB; 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iifii.initial_client_SP 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = setup_client_stack( init_sp, env, 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &info, &iifii.client_auxv, 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iicii.clstack_top, iifii.clstack_max_size ); 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(env); 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "initimg", 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Client info: " 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "initial_IP=%p initial_TOC=%p brk_base=%p\n", 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)(iifii.initial_client_IP), 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)(iifii.initial_client_TOC), 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)VG_(brk_base) ); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "initimg", 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Client info: " 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "initial_SP=%p max_stack_size=%ld\n", 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)(iifii.initial_client_SP), 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (SizeT)iifii.clstack_max_size ); 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //-------------------------------------------------------------- 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Setup client data (brk) segment. Initially a 1-page segment 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // which abuts a shrinkable reservation. 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // p: load_client() [for 'info' and hence VG_(brk_base)] 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //-------------------------------------------------------------- 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT m1 = 1024 * 1024; 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT m8 = 8 * m1; 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur; 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "initimg", "Setup client data (brk) segment\n"); 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dseg_max_size < m1) dseg_max_size = m1; 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dseg_max_size > m8) dseg_max_size = m8; 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dseg_max_size = VG_PGROUNDUP(dseg_max_size); 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown setup_client_dataseg( dseg_max_size ); 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iifii; 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== TOP-LEVEL: VG_(finalise_thread1state) ===*/ 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Just before starting the client, we may need to make final 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown adjustments to its initial image. Also we need to set up the VEX 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest state for thread 1 (the root thread) and copy in essential 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown starting values. This is handed the IIFinaliseImageInfo created by 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(ii_create_image). 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadArchState* arch = &VG_(threads)[1].arch; 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* On Linux we get client_{ip/sp/toc}, and start the client with 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all other registers zeroed. */ 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == sizeof(VexGuestX86State) % 16); 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the initial state, and set up the simulated FPU in a 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sane way. */ 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestX86_initialise(&arch->vex); 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the shadow areas. */ 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State)); 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State)); 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Put essential stuff into the new state. */ 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_ESP = iifii.initial_client_SP; 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_EIP = iifii.initial_client_IP; 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* initialise %cs, %ds and %ss to point at the operating systems 1003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default code, data and stack segments. Also %es (see #291253). */ 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS)); 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS)); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS)); 1007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng asm volatile("movw %%es, %0" : : "m" (arch->vex.guest_ES)); 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == sizeof(VexGuestAMD64State) % 16); 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the initial state, and set up the simulated FPU in a 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sane way. */ 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestAMD64_initialise(&arch->vex); 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the shadow areas. */ 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State)); 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State)); 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Put essential stuff into the new state. */ 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_RSP = iifii.initial_client_SP; 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_RIP = iifii.initial_client_IP; 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc32_linux) 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == sizeof(VexGuestPPC32State) % 16); 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the initial state, and set up the simulated FPU in a 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sane way. */ 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestPPC32_initialise(&arch->vex); 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the shadow areas. */ 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestPPC32State)); 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestPPC32State)); 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Put essential stuff into the new state. */ 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_GPR1 = iifii.initial_client_SP; 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_CIA = iifii.initial_client_IP; 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_linux) 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == sizeof(VexGuestPPC64State) % 16); 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the initial state, and set up the simulated FPU in a 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sane way. */ 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestPPC64_initialise(&arch->vex); 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the shadow areas. */ 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestPPC64State)); 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestPPC64State)); 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Put essential stuff into the new state. */ 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_GPR1 = iifii.initial_client_SP; 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_GPR2 = iifii.initial_client_TOC; 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_CIA = iifii.initial_client_IP; 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_arm_linux) 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the initial state, and set up the simulated FPU in a 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sane way. */ 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestARM_initialise(&arch->vex); 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero out the shadow areas. */ 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestARMState)); 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestARMState)); 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_R13 = iifii.initial_client_SP; 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_R15T = iifii.initial_client_IP; 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is just EABI stuff. */ 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME jrs: what's this for? 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arch->vex.guest_R1 = iifii.initial_client_SP; 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# elif defined(VGP_s390x_linux) 1072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(0 == sizeof(VexGuestS390XState) % 16); 1073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Zero out the initial state. This also sets the guest_fpc to 0, which 1075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov is also done by the kernel for the fpc during execve. */ 1076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov LibVEX_GuestS390X_initialise(&arch->vex); 1077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Mark all registers as undefined ... */ 1079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memset)(&arch->vex_shadow1, 0xFF, sizeof(VexGuestS390XState)); 1080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memset)(&arch->vex_shadow2, 0x00, sizeof(VexGuestS390XState)); 1081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* ... except SP, FPC, and IA */ 1082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memset)((UChar *)&arch->vex_shadow1 + VG_O_STACK_PTR, 0x00, 8); 1083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memset)((UChar *)&arch->vex_shadow1 + VG_O_FPC_REG, 0x00, 4); 1084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memset)((UChar *)&arch->vex_shadow1 + VG_O_INSTR_PTR, 0x00, 8); 1085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Put essential stuff into the new state. */ 1087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov arch->vex.guest_SP = iifii.initial_client_SP; 1088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov arch->vex.guest_IA = iifii.initial_client_IP; 1089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* See sys_execve in <linux>/arch/s390/kernel/process.c */ 1090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arch->vex.guest_fpc = 0; 1091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Tell the tool about the registers we just wrote */ 1093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_STACK_PTR, 8); 1094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_FPC_REG, 4); 1095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_INSTR_PTR, 8); 1096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 1097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_mips32_linux) 1099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(0 == sizeof(VexGuestMIPS32State) % 16); 1100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Zero out the initial state, and set up the simulated FPU in a 1101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sane way. */ 1102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng LibVEX_GuestMIPS32_initialise(&arch->vex); 1103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Zero out the shadow areas. */ 1105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestMIPS32State)); 1106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestMIPS32State)); 1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arch->vex.guest_r29 = iifii.initial_client_SP; 1109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arch->vex.guest_PC = iifii.initial_client_IP; 1110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arch->vex.guest_r31 = iifii.initial_client_SP; 1111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown platform 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Tell the tool that we just wrote to the registers. */ 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0, 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(VexGuestArchState)); 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux) 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1126