18eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
28eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*--------------------------------------------------------------------*/
38eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*--- Startup: create initial process image on Solaris             ---*/
48eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*---                                            initimg-solaris.c ---*/
58eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*--------------------------------------------------------------------*/
68eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
78eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*
88eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   This file is part of Valgrind, a dynamic binary instrumentation
98eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   framework.
108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
11ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2011-2017 Petr Pavlu
128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      setup@dagobah.cz
138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   This program is free software; you can redistribute it and/or
158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   modify it under the terms of the GNU General Public License as
168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   published by the Free Software Foundation; either version 2 of the
178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   License, or (at your option) any later version.
188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   This program is distributed in the hope that it will be useful, but
208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   General Public License for more details.
238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   You should have received a copy of the GNU General Public License
258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   along with this program; if not, write to the Free Software
268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   02111-1307, USA.
288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   The GNU General Public License is contained in the file COPYING.
308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj*/
318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
32ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes/* Copyright 2013-2017, Ivo Raisr <ivosh@ivosh.net>. */
33e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_solaris)
358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Note: This file is based on initimg-linux.c. */
378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_basics.h"
398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_vki.h"
408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_debuglog.h"
418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_libcbase.h"
428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_libcassert.h"
438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_libcfile.h"
448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_libcproc.h"
458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_libcprint.h"
468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_xarray.h"
478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_clientstate.h"
488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_aspacemgr.h"
498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_mallocfree.h"
508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_machine.h"
518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_ume.h"
528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_options.h"
53bcfaeedb1e1ac2625eea81951a785a777834321ciraisr#include "pub_core_syswrap.h"
548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_tooliface.h"       /* VG_TRACK */
558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_threadstate.h"     /* ThreadArchState */
568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "priv_initimg_pathscan.h"
578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include "pub_core_initimg.h"         /* self */
588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*=== Loading the client                                           ===*/
628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Load the client whose name is VG_(argv_the_exename). */
658eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic void load_client(/*OUT*/ExeInfo *info,
668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                        /*OUT*/HChar *out_exe_name, SizeT out_exe_name_size)
678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   const HChar *exe_name;
698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Int ret;
708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SysRes res;
718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(VG_(args_the_exename));
738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   exe_name = ML_(find_executable)(VG_(args_the_exename));
748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (!exe_name) {
768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Return POSIX's NOTFOUND. */
788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(exit)(127);
798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /*NOTREACHED*/
808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(memset)(info, 0, sizeof(*info));
838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ret = VG_(do_exec)(exe_name, info);
848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (ret < 0) {
858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(printf)("valgrind: could not execute '%s'\n", exe_name);
868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(exit)(1);
878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /*NOTREACHED*/
888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* The client was successfully loaded!  Continue. */
918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Save resolved exename. */
938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (VG_(strlen)(exe_name) + 1 > out_exe_name_size) {
948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* This should not really happen. */
958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(printf)("valgrind: execname %s is too long\n", exe_name);
968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(exit)(1);
978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /*NOTREACHED*/
988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(strcpy)(out_exe_name, exe_name);
1008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Get hold of a file descriptor which refers to the client executable.
1028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      This is needed for attaching to GDB. */
1038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
1048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (!sr_isError(res))
1058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(cl_exec_fd) = sr_Res(res);
1068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Set initial brk values. */
108bcfaeedb1e1ac2625eea81951a785a777834321ciraisr   if (info->ldsoexec) {
109bcfaeedb1e1ac2625eea81951a785a777834321ciraisr      VG_(brk_base) = VG_(brk_limit) = -1;
110bcfaeedb1e1ac2625eea81951a785a777834321ciraisr   } else {
111bcfaeedb1e1ac2625eea81951a785a777834321ciraisr      VG_(brk_base) = VG_(brk_limit) = info->brkbase;
112bcfaeedb1e1ac2625eea81951a785a777834321ciraisr   }
1138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
1148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
1178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*=== Setting up the client's environment                          ===*/
1188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
1198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Prepare the client's environment.  This is basically a copy of our
1218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   environment, except:
1228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     LD_PRELOAD=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
1248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
1258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                $LD_PRELOAD
1268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   If this is missing, then it is added.
1288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Also, remove any binding for VALGRIND_LAUNCHER=.  The client should not be
1308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   able to see this.
1318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   If this needs to handle any more variables it should be hacked into
1338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   something table driven.  The copy is VG_(malloc)'d space.
1348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj*/
1358eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic HChar **setup_client_env(HChar **origenv, const HChar *toolname)
1368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
1378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   const HChar *ld_preload = "LD_PRELOAD=";
1388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT ld_preload_len = VG_(strlen)(ld_preload);
1398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Bool ld_preload_done = False;
1408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT vglib_len = VG_(strlen)(VG_(libdir));
1418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar **cpp;
1438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar **ret;
1448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar *preload_tool_path;
1458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT envc, i;
1468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Alloc space for the
1488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj        <path>/vgpreload_core-<platform>.so and
1498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj        <path>/vgpreload_<tool>-<platform>.so
1508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      paths.  We might not need the space for the tool path, but it doesn't
1518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      hurt to over-allocate briefly.  */
1528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT preload_core_path_size = vglib_len + sizeof("/vgpreload_core-") - 1
1538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                            + sizeof(VG_PLATFORM) - 1
1548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                            + sizeof(".so");
1558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT preload_tool_path_size = vglib_len + sizeof("/vgpreload_") - 1
1568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                            + VG_(strlen)(toolname) + 1 /*-*/
1578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                            + sizeof(VG_PLATFORM) - 1
1588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                            + sizeof(".so");
1598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT preload_string_size = preload_core_path_size
1608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                               + preload_tool_path_size;
1618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar *preload_string = VG_(malloc)("initimg-solaris.sce.1",
1628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                       preload_string_size);
1638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Check that the parameters are sane. */
1658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(origenv);
1668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(toolname);
1678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Determine if there's a vgpreload_<tool>-<platform>.so file, and setup
1698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      preload_string. */
1708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   preload_tool_path = VG_(malloc)("initimg-solaris.sce.2",
1718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                   preload_tool_path_size);
1728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(sprintf)(preload_tool_path, "%s/vgpreload_%s-%s.so", VG_(libdir),
1738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                toolname, VG_PLATFORM);
1748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (!VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/)) {
1758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* The tool's .so exists, put it into LD_PRELOAD with the core's so. */
1768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(sprintf)(preload_string, "%s/vgpreload_core-%s.so:%s", VG_(libdir),
1778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                   VG_PLATFORM, preload_tool_path);
1788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
1798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   else {
1808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* The tool's .so doesn't exist, put only the core's .so into
1818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         LD_PRELOAD. */
1828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(sprintf)(preload_string, "%s/vgpreload_core-%s.so", VG_(libdir),
1838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                   VG_PLATFORM);
1848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
1858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(free)(preload_tool_path);
1868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(debugLog)(2, "initimg", "preload_string:\n");
1888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(debugLog)(2, "initimg", "  \"%s\"\n", preload_string);
1898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Count the original size of the env. */
1918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   envc = 0;
1928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   for (cpp = origenv; *cpp; cpp++)
1938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      envc++;
1948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Allocate a new space, envc + 1 new entry + NULL. */
1968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ret = VG_(malloc)("initimg-solaris.sce.3", sizeof(HChar*) * (envc + 1 + 1));
1978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Copy it over. */
1998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   for (cpp = ret; *origenv; )
2008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      *cpp++ = *origenv++;
2018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *cpp = NULL;
2028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(envc == cpp - ret);
2048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Walk over the new environment, mashing as we go. */
2068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   for (cpp = ret; *cpp; cpp++) {
2078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len))
2088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         continue;
2098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* LD_PRELOAD entry found, smash it. */
2118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT size = VG_(strlen)(*cpp) + 1 /*:*/
2128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                     + preload_string_size;
2138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      HChar *cp = VG_(malloc)("initimg-solaris.sce.4", size);
2148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(sprintf)(cp, "%s%s:%s", ld_preload, preload_string,
2168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                   (*cpp) + ld_preload_len);
2178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      *cpp = cp;
2188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ld_preload_done = True;
2208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
2218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Add the missing bits. */
2238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (!ld_preload_done) {
2248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT size = ld_preload_len + preload_string_size;
2258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      HChar *cp = VG_(malloc)("initimg-solaris.sce.5", size);
2268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(sprintf)(cp, "%s%s", ld_preload, preload_string);
2288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ret[envc++] = cp;
2298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
2308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* We've got ret[0 .. envc-1] live now. */
2328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Find and remove a binding for VALGRIND_LAUNCHER. */
2348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   {
2358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      const HChar *v_launcher = VALGRIND_LAUNCHER "=";
2368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT v_launcher_len = VG_(strlen)(v_launcher);
2378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      for (i = 0; i < envc; i++)
239a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes         if (!VG_(memcmp)(ret[i], v_launcher, v_launcher_len)) {
2408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            /* VALGRIND_LAUNCHER was found. */
2418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            break;
2428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         }
2438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (i < envc) {
2458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* VALGRIND_LAUNCHER was found, remove it. */
2468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         for (; i < envc - 1; i++)
2478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            ret[i] = ret[i + 1];
2488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         envc--;
2498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
2508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
2518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(free)(preload_string);
2538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ret[envc] = NULL;
2548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return ret;
2568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
2578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
2608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*=== Setting up the client's stack                                ===*/
2618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
2628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Add a string onto the string table, and return its address. */
2648eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic HChar *copy_str(HChar **tab, const HChar *str)
2658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
2668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar *cp = *tab;
2678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar *orig = cp;
2688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   while (*str)
2708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      *cp++ = *str++;
2718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *cp++ = '\0';
2728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *tab = cp;
2748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return orig;
2768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
2778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
2786150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr#if defined(SOLARIS_RESERVE_SYSSTAT_ADDR) || \
2796150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr    defined(SOLARIS_RESERVE_SYSSTAT_ZONE_ADDR)
2806150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr#define ORIG_AUXV_PRESENT 1
2816150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr#endif
2826150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr
2836150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr#if defined(ORIG_AUXV_PRESENT)
284e03654002556aa3ece73c344ec8c8cbe15754df1iraisr/* The auxiliary vector might not be present. So we cross-check pointers from
285e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   argv and envp pointing to the string table. */
286e03654002556aa3ece73c344ec8c8cbe15754df1iraisrstatic vki_auxv_t *find_original_auxv(Addr init_sp)
287e03654002556aa3ece73c344ec8c8cbe15754df1iraisr{
288e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   HChar **sp = (HChar **) init_sp;
289e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   HChar *lowest_str_ptr = (HChar *) UINTPTR_MAX; // lowest ptr to string table
290e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
291e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   sp++; // skip argc
292e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
293e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   while (*sp != NULL) { // skip argv
294e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      if (*sp < lowest_str_ptr)
295e03654002556aa3ece73c344ec8c8cbe15754df1iraisr         lowest_str_ptr = *sp;
296e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      sp++;
297e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   }
298e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   sp++;
299e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
300e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   while (*sp != 0) { // skip env
301e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      if (*sp < lowest_str_ptr)
302e03654002556aa3ece73c344ec8c8cbe15754df1iraisr         lowest_str_ptr = *sp;
303e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      sp++;
304e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   }
305e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   sp++;
306e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
307e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   if ((Addr) sp < (Addr) lowest_str_ptr) {
308e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      return (vki_auxv_t *) sp;
309e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   } else {
310e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      return NULL;
311e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   }
312e03654002556aa3ece73c344ec8c8cbe15754df1iraisr}
313e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
314e03654002556aa3ece73c344ec8c8cbe15754df1iraisrstatic void copy_auxv_entry(const vki_auxv_t *orig_auxv, Int type,
315e03654002556aa3ece73c344ec8c8cbe15754df1iraisr                            const HChar *type_name, vki_auxv_t *auxv)
316e03654002556aa3ece73c344ec8c8cbe15754df1iraisr{
317e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   vg_assert(auxv != NULL);
318e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
319e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   if (orig_auxv == NULL) {
320e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      VG_(printf)("valgrind: Cannot locate auxiliary vector.\n");
321e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      VG_(printf)("valgrind: Cannot continue. Sorry.\n\n");
322e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      VG_(exit)(1);
323e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   }
324e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
325e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   for ( ; orig_auxv->a_type != VKI_AT_NULL; orig_auxv++) {
326e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      if (orig_auxv->a_type == type) {
327e03654002556aa3ece73c344ec8c8cbe15754df1iraisr         auxv->a_type = type;
328e03654002556aa3ece73c344ec8c8cbe15754df1iraisr         auxv->a_un.a_val = orig_auxv->a_un.a_val;
329e03654002556aa3ece73c344ec8c8cbe15754df1iraisr         return;
330e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      }
331e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   }
332e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
333e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   VG_(printf)("valgrind: Cannot locate %s in the aux\n", type_name);
334e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   VG_(printf)("valgrind: vector. Cannot continue. Sorry.\n\n");
335e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   VG_(exit)(1);
336e03654002556aa3ece73c344ec8c8cbe15754df1iraisr}
3376150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr#endif /* ORIG_AUXV_PRESENT */
3388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
3398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* This sets up the client's initial stack, containing the args,
3408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   environment and aux vector.
3418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
3428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   The format of the stack is:
3438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
3448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   higher address +-----------------+ <- clstack_end
3458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  |                 |
3468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  : string table    :
3478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  |                 |
3488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  +-----------------+
3498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  | AT_NULL         |
3508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  -                 -
3518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  | auxv            |
3528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  +-----------------+
3538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  | NULL            |
3548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  -                 -
3558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  | envp            |
3568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  +-----------------+
3578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  | NULL            |
3588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  -                 -
3598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  | argv            |
3608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  +-----------------+
3618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  | argc            |
3628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   lower address  +-----------------+ <- sp
3638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  | undefined       |
3648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  :                 :
3658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
3668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Allocate and create the initial client stack.  It is allocated down from
3678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   clstack_end, which was previously determined by the address space manager.
3688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   The returned value is the SP value for the client.
3698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
370e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   Note that auxiliary vector is *not* created by kernel on illumos and
371e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   Solaris 11 if the program is statically linked (which is our case).
372e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   Although we now taught Solaris 12 to create the auxiliary vector, we still
373e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   have to build auxv from scratch, to make the code consistent. */
3748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
375e03654002556aa3ece73c344ec8c8cbe15754df1iraisrstatic Addr setup_client_stack(Addr init_sp,
3768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                               HChar **orig_envp,
3778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                               const ExeInfo *info,
3788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                               Addr clstack_end,
3798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                               SizeT clstack_max_size,
3808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                               const HChar *resolved_exe_name)
3818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
3828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SysRes res;
3838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar **cpp;
3848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar *strtab;       /* string table */
3858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar *stringbase;
3868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Addr *ptr;
3878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vki_auxv_t *auxv;
3888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT stringsize;    /* total size of strings in bytes */
3898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT auxsize;       /* total size of auxv in bytes */
3908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Int argc;            /* total argc */
3918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Int envc;            /* total number of env vars */
3928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT stacksize;     /* total client stack size */
3938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Addr client_SP;      /* client stack base (initial SP) */
3948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Addr clstack_start;
3958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Int i;
3968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
3978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(VG_IS_PAGE_ALIGNED(clstack_end + 1));
3988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(VG_(args_the_exename));
3998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(VG_(args_for_client));
4008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4016150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr#  if defined(ORIG_AUXV_PRESENT)
402e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   /* Get the original auxv (if any). */
403e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   vki_auxv_t *orig_auxv = find_original_auxv(init_sp);
4046150d3e63c6989aa7b6540ff75d6ae104ad3aa28iraisr#  endif /* ORIG_AUXV_PRESENT */
405e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
4068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* ==================== compute sizes ==================== */
4078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* First of all, work out how big the client stack will be. */
4098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   stringsize = 0;
4108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Paste on the extra args if the loader needs them (i.e. the #!
4128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      interpreter and its argument). */
4138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   argc = 0;
4148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (info->interp_name) {
4158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      argc++;
4168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      stringsize += VG_(strlen)(info->interp_name) + 1;
4178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
4188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (info->interp_args) {
4198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      argc++;
4208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      stringsize += VG_(strlen)(info->interp_args) + 1;
4218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
4228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Now scan the args we're given... */
4248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   argc++;
4258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   stringsize += VG_(strlen)(VG_(args_the_exename)) + 1;
4268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   for (i = 0; i < VG_(sizeXA)(VG_(args_for_client)); i++) {
4278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      argc++;
4288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      stringsize += VG_(strlen)(*(HChar**)
4298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                  VG_(indexXA)(VG_(args_for_client), i)) + 1;
4308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
4318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* ...and the environment. */
4338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   envc = 0;
4348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   for (cpp = orig_envp; *cpp; cpp++) {
4358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      envc++;
4368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      stringsize += VG_(strlen)(*cpp) + 1;
4378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
4388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Now, how big is the auxv?
4408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      AT_SUN_PLATFORM
4428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      AT_SUN_EXECNAME
443358f27ccb54ef77fbd0d6e199b4b5431dfb1b465iraisr      AT_PHDR            (not for elfs with no PT_PHDR, such as ld.so.1)
4448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      AT_BASE
445a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      AT_ENTRY
4468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      AT_FLAGS
4478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      AT_PAGESZ
4488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      AT_SUN_AUXFLAFGS
4498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      AT_SUN_HWCAP
450e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      AT_SUN_SYSSTAT_ADDR      (if supported)
451e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      AT_SUN_SYSSTAT_ZONE_ADDR (if supported)
4528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      AT_NULL
4538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
454a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      It would be possible to also add AT_PHENT, AT_PHNUM, AT_SUN_LDDATA,
455a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      but they don't seem to be so important. */
456a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   auxsize = 10 * sizeof(*auxv);
457e03654002556aa3ece73c344ec8c8cbe15754df1iraisr#  if defined(SOLARIS_RESERVE_SYSSTAT_ADDR)
458e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   auxsize += sizeof(*auxv);
459e03654002556aa3ece73c344ec8c8cbe15754df1iraisr#  endif
460e03654002556aa3ece73c344ec8c8cbe15754df1iraisr#  if defined(SOLARIS_RESERVE_SYSSTAT_ZONE_ADDR)
461e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   auxsize += sizeof(*auxv);
462e03654002556aa3ece73c344ec8c8cbe15754df1iraisr#  endif
463e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
4648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  if defined(VGA_x86) || defined(VGA_amd64)
4658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_SUN_PLATFORM string. */
4668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   stringsize += VG_(strlen)("i86pc") + 1;
4678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  else
4688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    error "Unknown architecture"
4698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  endif
4708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_SUN_EXECNAME string. */
4718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   stringsize += VG_(strlen)(resolved_exe_name) + 1;
4728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Calculate how big the client stack is. */
4748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   stacksize =
4758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      sizeof(Word) +                            /* argc */
4768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      sizeof(HChar**) +                         /* argc[0] == exename */
4778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      sizeof(HChar**) * argc +                  /* argv */
4788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      sizeof(HChar**) +                         /* terminal NULL */
4798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      sizeof(HChar**) * envc +                  /* envp */
4808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      sizeof(HChar**) +                         /* terminal NULL */
4818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      auxsize +                                 /* auxv */
4828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_ROUNDUP(stringsize, sizeof(Word));     /* strings (aligned) */
4838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* The variable client_SP is the client's stack pointer. */
4858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   client_SP = clstack_end - stacksize;
4868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   client_SP = VG_ROUNDDN(client_SP, 16); /* Make stack 16 byte aligned. */
4878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Calculate base of the string table (aligned). */
4898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   stringbase = (HChar*)clstack_end - VG_ROUNDUP(stringsize, sizeof(Int));
4908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   strtab = stringbase;
4918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   clstack_start = VG_PGROUNDDN(client_SP);
4938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Calculate the max stack size. */
4958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   clstack_max_size = VG_PGROUNDUP(clstack_max_size);
4968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Record stack extent -- needed for stack-change code. */
4988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(clstk_start_base) = clstack_start;
4998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(clstk_end) = clstack_end;
5008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(clstk_max_size) = clstack_max_size;
5018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (0)
5038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(printf)("stringsize=%lu, auxsize=%lu, stacksize=%lu, maxsize=%#lx\n"
5048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  "clstack_start %#lx\n"
5058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  "clstack_end   %#lx\n",
5068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  stringsize, auxsize, stacksize, clstack_max_size,
5078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  clstack_start, clstack_end);
5088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* ==================== allocate space ==================== */
5108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   {
5128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT anon_size = clstack_end - clstack_start + 1;
5138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT resvn_size = clstack_max_size - anon_size;
5148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      Addr anon_start = clstack_start;
5158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      Addr resvn_start = anon_start - resvn_size;
5168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT inner_HACK = 0;
5178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      Bool ok;
5188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* So far we've only accounted for space requirements down to the stack
5208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         pointer.  If this target's ABI requires a redzone below the stack
5218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         pointer, we need to allocate an extra page, to handle the worst case
5228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         in which the stack pointer is almost at the bottom of a page, and so
5238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         there is insufficient room left over to put the redzone in.  In this
5248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         case the simple thing to do is allocate an extra page, by shrinking
5258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         the reservation by one page and growing the anonymous area by a
5268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         corresponding page. */
5278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(VG_STACK_REDZONE_SZB >= 0);
5288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE);
5298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (VG_STACK_REDZONE_SZB > 0) {
5308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         vg_assert(resvn_size > VKI_PAGE_SIZE);
5318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         resvn_size -= VKI_PAGE_SIZE;
5328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         anon_start -= VKI_PAGE_SIZE;
5338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         anon_size += VKI_PAGE_SIZE;
5348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
5358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
5378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
5388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
5398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
5408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
5418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#     ifdef ENABLE_INNER
5438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Create 1M non-fault-extending stack. */
5448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      inner_HACK = 1024 * 1024;
5458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#     endif
5468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (0)
5488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         VG_(printf)("resvn_start=%#lx, resvn_size=%#lx\n"
5498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                     "anon_start=%#lx, anon_size=%#lx\n",
5508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                     resvn_start, resvn_size, anon_start, anon_size);
5518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Create a shrinkable reservation followed by an anonymous segment.
5538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         Together these constitute a growdown stack. */
5548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ok = VG_(am_create_reservation)(resvn_start,
5558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                      resvn_size - inner_HACK,
5568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                      SmUpper,
5578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                      anon_size + inner_HACK);
5588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (ok) {
5598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* Allocate a stack - mmap enough space for the stack. */
5608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         res = VG_(am_mmap_anon_fixed_client)(anon_start - inner_HACK,
5618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                              anon_size + inner_HACK,
5628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                              info->stack_prot);
5638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
5648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (!ok || sr_isError(res)) {
5658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* Allocation of the stack failed.  We have to stop. */
5668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         VG_(printf)("valgrind: "
5678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                     "I failed to allocate space for the application's stack.\n");
5688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         VG_(printf)("valgrind: "
5698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                     "This may be the result of a very large --main-stacksize=\n");
5708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         VG_(printf)("valgrind: setting.  Cannot continue.  Sorry.\n\n");
5718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         VG_(exit)(1);
5728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /*NOTREACHED*/
5738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
5748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
5758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* ==================== create client stack ==================== */
5778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ptr = (Addr*)client_SP;
5798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Copy-out client argc. */
5818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *ptr++ = argc;
5828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Copy-out client argv. */
584a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   if (info->interp_name)
5858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
586a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   if (info->interp_args)
5878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
5888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
5908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   for (i = 0; i < VG_(sizeXA)(VG_(args_for_client)); i++)
5918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      *ptr++ = (Addr)copy_str(
5928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                  &strtab, *(HChar**) VG_(indexXA)(VG_(args_for_client), i));
5938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *ptr++ = 0;
5948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
5958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Copy-out envp. */
5968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(client_envp) = (HChar**)ptr;
5978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   for (cpp = orig_envp; *cpp; ptr++, cpp++)
5988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      *ptr = (Addr)copy_str(&strtab, *cpp);
5998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *ptr++ = 0;
6008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Create aux vector. */
6028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv = (auxv_t*)ptr;
6038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(client_auxv) = (UWord*)ptr;
6048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_SUN_PLATFORM */
6068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_type = VKI_AT_SUN_PLATFORM;
6078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  if defined(VGA_x86) || defined(VGA_amd64)
6088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_un.a_ptr = copy_str(&strtab, "i86pc");
6098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  else
6108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    error "Unknown architecture"
6118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  endif
6128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv++;
6138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_SUN_EXECNAME */
6158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_type = VKI_AT_SUN_EXECNAME;
6168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_un.a_ptr = copy_str(&strtab, resolved_exe_name);
6178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv++;
6188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_PHDR */
620358f27ccb54ef77fbd0d6e199b4b5431dfb1b465iraisr   if ((info->real_phdr_present) && (info->phdr != 0)) {
6218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      auxv->a_type = VKI_AT_PHDR;
6228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      auxv->a_un.a_val = info->phdr;
6238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      auxv++;
6248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
6258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_BASE */
6278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_type = VKI_AT_BASE;
6288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_un.a_val = info->interp_offset;
6298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv++;
6308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
631a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   /* AT_ENTRY */
632a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   auxv->a_type = VKI_AT_ENTRY;
633a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   auxv->a_un.a_val = info->entry;
634a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   auxv++;
635a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
6368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_FLAGS */
6378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_type = VKI_AT_FLAGS;
6388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  if defined(VGA_x86) || defined(VGA_amd64)
6398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_un.a_val = 0; /* 0 on i86pc */
6408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  else
6418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    error "Unknown architecture"
6428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  endif
6438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv++;
6448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_PAGESZ */
6468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_type = VKI_AT_PAGESZ;
6478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_un.a_val = VKI_PAGE_SIZE;
6488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv++;
6498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_SUN_AUXFLAFGS */
6518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_type = VKI_AT_SUN_AUXFLAGS;
6528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* XXX Handle AF_SUN_SETUGID? */
6538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_un.a_val = VKI_AF_SUN_HWCAPVERIFY;
6548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv++;
6558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_SUN_HWCAP */
6578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   {
6588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VexArch vex_arch;
6598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VexArchInfo vex_archinfo;
6608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      UInt hwcaps;
6618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(machine_get_VexArchInfo)(&vex_arch, &vex_archinfo);
6638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#     if defined(VGA_x86)
6658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(vex_arch == VexArchX86);
6668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Set default hwcaps. */
6688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      hwcaps =
6698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj           VKI_AV_386_FPU       /* x87-style floating point */
6708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_TSC       /* rdtsc insn */
6718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_CX8       /* cmpxchg8b insn */
6728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_SEP       /* sysenter and sysexit */
6738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_AMD_SYSC  /* AMD's syscall and sysret */
6748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_CMOV      /* conditional move insns */
6758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_MMX       /* MMX insn */
6768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_AHF;      /* lahf/sahf insns */
6778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Handle additional hwcaps. */
6798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE1)
6808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
6818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_FXSR   /* fxsave and fxrstor */
6828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            | VKI_AV_386_SSE;   /* SSE insns and regs  */
6838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE2) {
6848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         vg_assert(vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE1);
6858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
6868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_SSE2;  /* SSE2 insns and regs */
6878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
6888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE3) {
6898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         vg_assert(vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE2);
6908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
6918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_SSE3   /* SSE3 insns and regs */
6928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            | VKI_AV_386_SSSE3; /* Intel SSSE3 insns */
6938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
6948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_LZCNT)
6958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
6968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_AMD_LZCNT; /* AMD's LZCNT insn */
6978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
6988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* No support for:
6998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AMD_MMX         AMD's MMX insns
7008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AMD_3DNow       AMD's 3Dnow! insns
7018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AMD_3DNowx      AMD's 3Dnow! extended insns
7028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_CX16            cmpxchg16b insn
7038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_TSCP            rdtscp instruction
7048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AMD_SSE4A       AMD's SSE4A insns
7058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_POPCNT          POPCNT insn
7068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_SSE4_1          Intel SSE4.1 insns
7078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_SSE4_2          Intel SSE4.2 insns
7088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_MOVBE           Intel MOVBE insns
7098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AES             Intel AES insns
7108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_PCLMULQDQ       Intel PCLMULQDQ insn
7118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_XSAVE           Intel XSAVE/XRSTOR insns
7128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AVX             Intel AVX insns
7138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         illumos only:
7148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_VMX          Intel VMX support
7158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_AMD_SVM      AMD SVM support
7168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         solaris only:
7178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_AMD_XOP      AMD XOP insns
7188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_AMD_FMA4     AMD FMA4 insns */
7198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
7208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#     elif defined(VGA_amd64)
7218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      vg_assert(vex_arch == VexArchAMD64);
7228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
7238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Set default hwcaps. */
7248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      hwcaps =
7258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj           VKI_AV_386_FPU       /* x87-style floating point */
7268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_TSC       /* rdtsc insn */
7278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_CX8       /* cmpxchg8b insn */
7288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_AMD_SYSC  /* AMD's syscall and sysret */
7298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_CMOV      /* conditional move insns */
7308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_MMX       /* MMX insn */
7318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_AHF       /* lahf/sahf insns */
7328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_FXSR      /* fxsave and fxrstor */
7338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_SSE       /* SSE insns and regs  */
7348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         | VKI_AV_386_SSE2;     /* SSE2 insns and regs */
7358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
7368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Handle additional hwcaps. */
7378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3)
7388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
7398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_SSE3   /* SSE3 insns and regs */
7408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            | VKI_AV_386_SSSE3; /* Intel SSSE3 insns */
7418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16)
7428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
7438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_CX16;  /* cmpxchg16b insn */
7448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_LZCNT)
7458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
7468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_AMD_LZCNT; /* AMD's LZCNT insn */
7478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_RDTSCP)
7488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
7498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_TSCP;  /* rdtscp instruction */
7508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if ((vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3) &&
7518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj          (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16)) {
7528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* The CPUID simulation provided by VEX claims to have POPCNT, AES
7538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            and SSE4 (SSE4.1/SSE4.2) in the SSE3+CX16 configuration. */
7548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
7558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_POPCNT /* POPCNT insn */
7568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            | VKI_AV_386_AES    /* Intel AES insns */
7578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            | VKI_AV_386_SSE4_1 /* Intel SSE4.1 insns */
7588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            | VKI_AV_386_SSE4_2; /* Intel SSE4.2 insns */
7598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
7608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if ((vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3) &&
7618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj          (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16) &&
7628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj          (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_AVX)) {
7638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* The CPUID simulation provided by VEX claims to have PCLMULQDQ and
7648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            XSAVE in the SSE3+CX16+AVX configuration. */
7658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         hwcaps |=
7668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj              VKI_AV_386_PCLMULQDQ /* Intel PCLMULQDQ insn */
7678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            | VKI_AV_386_XSAVE; /* Intel XSAVE/XRSTOR insns */
7688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
7698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* No support for:
7708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_SEP             sysenter and sysexit
7718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AMD_MMX         AMD's MMX insns
7728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AMD_3DNow       AMD's 3Dnow! insns
7738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AMD_3DNowx      AMD's 3Dnow! extended insns
7748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AMD_SSE4A       AMD's SSE4A insns
7758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_MOVBE           Intel MOVBE insns
7768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         AV_386_AVX             Intel AVX insns
7778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         illumos only:
7788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_VMX          Intel VMX support
7798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_AMD_SVM      AMD SVM support
7808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         solaris only:
7818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_AMD_XOP      AMD XOP insns
7828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_AMD_FMA4     AMD FMA4 insns
7838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
7848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         TODO VEX supports AVX, BMI and AVX2. Investigate if they can be
7858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         enabled on Solaris/illumos.
7868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj       */
7878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
7888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#     else
7898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#       error "Unknown architecture"
7908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#     endif
7918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
7928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      auxv->a_type = VKI_AT_SUN_HWCAP;
7938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      auxv->a_un.a_val = hwcaps;
7948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      auxv++;
7958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
7968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
7978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_SUN_HWCAP2 */
7988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   {
7998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* No support for:
8008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         illumos only:
8018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_2_F16C       F16C half percision extensions
8028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV_386_2_RDRAND     RDRAND insn
8038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         solaris only:
8048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_RDRAND      Intel RDRAND insns
8058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_FMA         Intel FMA insn
8068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_F16C        IEEE half precn(float) insn
8078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_AMD_TBM     AMD TBM insn
8088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_BMI1        Intel BMI1 insn
8098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_FSGSBASE    Intel RD/WR FS/GSBASE insn
8108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_AVX2        Intel AVX2 insns
8118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_BMI2        Intel BMI2 insns
8128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_HLE         Intel HLE insns
8138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_RTM         Intel RTM insns
8148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_EFS         Intel Enhanced Fast String
8158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_RDSEED      Intel RDSEED insn
8168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_ADX         Intel ADX insns
8178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            AV2_386_PRFCHW      Intel PREFETCHW hint
8188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj       */
8198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
8208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
821e03654002556aa3ece73c344ec8c8cbe15754df1iraisr#  if defined(SOLARIS_RESERVE_SYSSTAT_ADDR)
822e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   /* AT_SUN_SYSSTAT_ADDR */
823e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   copy_auxv_entry(orig_auxv, VKI_AT_SUN_SYSSTAT_ADDR,
824e03654002556aa3ece73c344ec8c8cbe15754df1iraisr                   "AT_SUN_SYSSTAT_ADDR", auxv);
825e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   VG_(change_mapping_ownership)(auxv->a_un.a_val, True);
826e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   auxv++;
827e03654002556aa3ece73c344ec8c8cbe15754df1iraisr#  endif
828e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
829e03654002556aa3ece73c344ec8c8cbe15754df1iraisr#  if defined(SOLARIS_RESERVE_SYSSTAT_ZONE_ADDR)
830e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   /* AT_SUN_SYSSTAT_ZONE_ADDR */
831e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   copy_auxv_entry(orig_auxv, VKI_AT_SUN_SYSSTAT_ZONE_ADDR,
832e03654002556aa3ece73c344ec8c8cbe15754df1iraisr                   "AT_SUN_SYSSTAT_ZONE_ADDR", auxv);
833e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   VG_(change_mapping_ownership)(auxv->a_un.a_val, True);
834e03654002556aa3ece73c344ec8c8cbe15754df1iraisr   auxv++;
835e03654002556aa3ece73c344ec8c8cbe15754df1iraisr#  endif
836e03654002556aa3ece73c344ec8c8cbe15754df1iraisr
8378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* AT_NULL */
8388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_type = VKI_AT_NULL;
8398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   auxv->a_un.a_val = 0;
8408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(strtab - stringbase == stringsize);
8428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* The variable client_SP is now pointing at client's argc/argv. */
8448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (0)
8468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(printf)("startup SP = %#lx\n", client_SP);
8478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return client_SP;
8488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
8498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
8518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*=== TOP-LEVEL: VG_(setup_client_initial_image)                   ===*/
8528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
8538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Create the client's initial memory image. */
8558eb8bab992e3998c33770b0cdb16059a8b918a06sewardjIIFinaliseImageInfo VG_(ii_create_image)(IICreateImageInfo iicii,
8568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                         const VexArchInfo *vex_archinfo)
8578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
8588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ExeInfo info;
8598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar **env = NULL;
8608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar resolved_exe_name[VKI_PATH_MAX];
8618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   IIFinaliseImageInfo iifii;
8638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(memset)(&iifii, 0, sizeof(iifii));
8648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //--------------------------------------------------------------
8668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   // Load client executable, finding in $PATH if necessary
8678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //   p: early_process_cmd_line_options()  [for 'exec', 'need_help']
8688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //   p: layout_remaining_space            [so there's space]
8698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //--------------------------------------------------------------
8708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(debugLog)(1, "initimg", "Loading client\n");
8718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (!VG_(args_the_exename)) {
8738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(err_missing_prog)();
8748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /*NOTREACHED*/
8758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
8768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   load_client(&info, resolved_exe_name, sizeof(resolved_exe_name));
8788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   iifii.initial_client_IP = info.init_ip;
8798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Note: TOC isn't available on Solaris. */
8808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   iifii.initial_client_TOC = info.init_toc;
8818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   iifii.initial_client_TP = info.init_thrptr;
8828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Note that iifii.client_auxv is never set on Solaris, because it isn't
8838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      necessary to have this value in VG_(ii_finalise_image). */
8848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //--------------------------------------------------------------
8868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   // Set up client's environment
8878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //   p: set-libdir                       [for VG_(libdir)]
8888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //   p: early_process_cmd_line_options() [for toolname]
8898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //--------------------------------------------------------------
8908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(debugLog)(1, "initimg", "Setup client env\n");
8918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   env = setup_client_env(iicii.envp, iicii.toolname);
8928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
8938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //--------------------------------------------------------------
8948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   // Setup client stack and EIP
8958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //   p: load_client()     [for 'info']
8968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //   p: fix_environment() [for 'env']
8978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   //--------------------------------------------------------------
8988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   {
8998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* When allocating space for the client stack, take notice of the
9008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         --main-stacksize value.  This makes it possible to run programs with
9018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         very large (primary) stack requirements simply by specifying
9028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         --main-stacksize. */
9038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Logic is as follows:
9048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         - By default, use the client's current stack rlimit.
9058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         - If that exceeds 16M, clamp to 16M.
9068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         - If a larger --main-stacksize value is specified, use that instead.
9078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         - In all situations, the minimum allowed stack size is 1M.
9088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      */
909e03654002556aa3ece73c344ec8c8cbe15754df1iraisr      Addr init_sp = (Addr) (iicii.argv - 1);
9108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT m1  = 1024 * 1024;
9118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT m16 = 16 * m1;
9128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      SizeT szB = (SizeT)VG_(client_rlimit_stack).rlim_cur;
9138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (szB < m1)
9148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         szB = m1;
9158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (szB > m16)
9168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         szB = m16;
9178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (VG_(clo_main_stacksize) > 0)
9198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         szB = VG_(clo_main_stacksize);
9208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (szB < m1)
9218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         szB = m1;
9228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      szB = VG_PGROUNDUP(szB);
9248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(debugLog)(1, "initimg",
9258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                       "Setup client stack: size will be %ld\n", szB);
9268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      iifii.clstack_max_size = szB;
9288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      iifii.initial_client_SP = setup_client_stack(init_sp, env, &info,
9298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                                   iicii.clstack_end,
9308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                                   iifii.clstack_max_size,
9318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                                   resolved_exe_name);
9328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(free)(env);
9338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(debugLog)(2, "initimg", "Client info: "
9358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                       "initial_IP=%#lx, initial_TOC=%#lx, brk_base=%#lx\n",
9368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                       iifii.initial_client_IP, iifii.initial_client_TOC,
9378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                       VG_(brk_base));
9388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_(debugLog)(2, "initimg", "Client info: "
9398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                       "initial_SP=%#lx, max_stack_size=%lu\n",
9408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                       iifii.initial_client_SP,
9418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                       iifii.clstack_max_size);
9428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
9438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
944bcfaeedb1e1ac2625eea81951a785a777834321ciraisr   if (info.ldsoexec) {
945bcfaeedb1e1ac2625eea81951a785a777834321ciraisr      /* We are executing the runtime linker itself.
946bcfaeedb1e1ac2625eea81951a785a777834321ciraisr         Initial data (brk) segment is setup on demand, after the target dynamic
947bcfaeedb1e1ac2625eea81951a785a777834321ciraisr         executable has been loaded or when a first brk() syscall is made.
948bcfaeedb1e1ac2625eea81951a785a777834321ciraisr         It cannot be established now because it would conflict with a temporary
949bcfaeedb1e1ac2625eea81951a785a777834321ciraisr         stack which ld.so.1 (when executed directly) uses for loading the
950bcfaeedb1e1ac2625eea81951a785a777834321ciraisr         target dynamic executable. See PRE(sys_brk) in syswrap-solaris.c. */
951bcfaeedb1e1ac2625eea81951a785a777834321ciraisr   } else {
952bcfaeedb1e1ac2625eea81951a785a777834321ciraisr      if (!VG_(setup_client_dataseg)()) {
953bcfaeedb1e1ac2625eea81951a785a777834321ciraisr         VG_(printf)("valgrind: cannot initialize data segment (brk).\n");
954bcfaeedb1e1ac2625eea81951a785a777834321ciraisr         VG_(exit)(1);
955bcfaeedb1e1ac2625eea81951a785a777834321ciraisr      }
956bcfaeedb1e1ac2625eea81951a785a777834321ciraisr   }
957bcfaeedb1e1ac2625eea81951a785a777834321ciraisr
958a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   VG_(free)(info.interp_name);
959a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   VG_(free)(info.interp_args);
9608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return iifii;
9618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
9628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
9658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*=== TOP-LEVEL: VG_(finalise_image)                               ===*/
9668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*====================================================================*/
9678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Just before starting the client, we may need to make final adjustments to
9698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   its initial image.  Also we need to set up the VEX guest state for thread 1
9708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   (the root thread) and copy in essential starting values.  This is handed
9718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   the IIFinaliseImageInfo created by VG_(ii_create_image).
9728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj*/
9738eb8bab992e3998c33770b0cdb16059a8b918a06sewardjvoid VG_(ii_finalise_image)(IIFinaliseImageInfo iifii)
9748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
9758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ThreadArchState *arch = &VG_(threads)[1].arch;
9768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  if defined(VGA_x86)
9788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(0 == sizeof(VexGuestX86State) % LibVEX_GUEST_STATE_ALIGN);
9798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Zero out the initial state, and set up the simulated FPU in a sane
9818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      way. */
9828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   LibVEX_GuestX86_initialise(&arch->vex);
9838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Zero out the shadow areas. */
9858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State));
9868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State));
9878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Put essential stuff into the new state. */
9898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   arch->vex.guest_ESP = iifii.initial_client_SP;
9908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   arch->vex.guest_EIP = iifii.initial_client_IP;
9918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   LibVEX_GuestX86_put_eflags(VKI_PSL_USER, &arch->vex);
9928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Set %cs, %ds, %ss and %es to default values. */
9948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   __asm__ __volatile__ ("movw %%cs, %[cs]" : [cs] "=m" (arch->vex.guest_CS));
9958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   __asm__ __volatile__ ("movw %%ds, %[ds]" : [ds] "=m" (arch->vex.guest_DS));
9968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   __asm__ __volatile__ ("movw %%ss, %[ss]" : [ss] "=m" (arch->vex.guest_SS));
9978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   __asm__ __volatile__ ("movw %%es, %[es]" : [es] "=m" (arch->vex.guest_ES));
9988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
9998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   {
10008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Initial thread pointer value will be saved in GDT when the thread is
10018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         started in the syswrap module and a thread's GDT is allocated. */
10028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ThreadOSstate *os = &VG_(threads)[1].os_state;
10038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      os->thrptr = iifii.initial_client_TP;
10048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
10058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
10068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  elif defined(VGA_amd64)
10078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   vg_assert(0 == sizeof(VexGuestAMD64State) % LibVEX_GUEST_STATE_ALIGN);
10088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
10098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Zero out the initial state, and set up the simulated FPU in a sane
10108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      way. */
10118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   LibVEX_GuestAMD64_initialise(&arch->vex);
10128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
10138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Zero out the shadow areas. */
10148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State));
10158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State));
10168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
10178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Put essential stuff into the new state. */
10188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   arch->vex.guest_RSP = iifii.initial_client_SP;
10198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   arch->vex.guest_RIP = iifii.initial_client_IP;
10208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   arch->vex.guest_FS_CONST = iifii.initial_client_TP;
10218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   LibVEX_GuestAMD64_put_rflags(VKI_PSL_USER, &arch->vex);
10228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
10238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  else
10248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    error "Unknown platform"
10258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  endif
10268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
10278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Tell the tool that we just wrote to the registers. */
10288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   VG_TRACK(post_reg_write, Vg_CoreStartup, 1/*tid*/, 0/*offset*/,
10298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            sizeof(VexGuestArchState));
10308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1031bcfaeedb1e1ac2625eea81951a785a777834321ciraisr   if (VG_(brk_base) != -1 ) {
1032bcfaeedb1e1ac2625eea81951a785a777834321ciraisr      /* Make inaccessible/unaddressable the end of the client data segment.
1033bcfaeedb1e1ac2625eea81951a785a777834321ciraisr         See PRE(sys_brk) in syswrap-solaris.c for details. */
1034bcfaeedb1e1ac2625eea81951a785a777834321ciraisr      VG_(track_client_dataseg)(1 /* tid */);
10351c628f3016f3437eda3294da1df7fcedef96d1d9iraisr   }
10368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
10378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
10388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif // defined(VGO_solaris)
10398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
10408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*--------------------------------------------------------------------*/
10418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*---                                                              ---*/
10428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*--------------------------------------------------------------------*/
1043