117c110443e39c0c63bb298689cad31e0b4671dfesewardj
217c110443e39c0c63bb298689cad31e0b4671dfesewardj/*--------------------------------------------------------------------*/
317c110443e39c0c63bb298689cad31e0b4671dfesewardj/*--- Startup: create initial process image on Linux               ---*/
417c110443e39c0c63bb298689cad31e0b4671dfesewardj/*---                                              initimg-linux.c ---*/
517c110443e39c0c63bb298689cad31e0b4671dfesewardj/*--------------------------------------------------------------------*/
617c110443e39c0c63bb298689cad31e0b4671dfesewardj
717c110443e39c0c63bb298689cad31e0b4671dfesewardj/*
817c110443e39c0c63bb298689cad31e0b4671dfesewardj   This file is part of Valgrind, a dynamic binary instrumentation
917c110443e39c0c63bb298689cad31e0b4671dfesewardj   framework.
1017c110443e39c0c63bb298689cad31e0b4671dfesewardj
11ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2000-2017 Julian Seward
1217c110443e39c0c63bb298689cad31e0b4671dfesewardj      jseward@acm.org
1317c110443e39c0c63bb298689cad31e0b4671dfesewardj
1417c110443e39c0c63bb298689cad31e0b4671dfesewardj   This program is free software; you can redistribute it and/or
1517c110443e39c0c63bb298689cad31e0b4671dfesewardj   modify it under the terms of the GNU General Public License as
1617c110443e39c0c63bb298689cad31e0b4671dfesewardj   published by the Free Software Foundation; either version 2 of the
1717c110443e39c0c63bb298689cad31e0b4671dfesewardj   License, or (at your option) any later version.
1817c110443e39c0c63bb298689cad31e0b4671dfesewardj
1917c110443e39c0c63bb298689cad31e0b4671dfesewardj   This program is distributed in the hope that it will be useful, but
2017c110443e39c0c63bb298689cad31e0b4671dfesewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
2117c110443e39c0c63bb298689cad31e0b4671dfesewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2217c110443e39c0c63bb298689cad31e0b4671dfesewardj   General Public License for more details.
2317c110443e39c0c63bb298689cad31e0b4671dfesewardj
2417c110443e39c0c63bb298689cad31e0b4671dfesewardj   You should have received a copy of the GNU General Public License
2517c110443e39c0c63bb298689cad31e0b4671dfesewardj   along with this program; if not, write to the Free Software
2617c110443e39c0c63bb298689cad31e0b4671dfesewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
2717c110443e39c0c63bb298689cad31e0b4671dfesewardj   02111-1307, USA.
2817c110443e39c0c63bb298689cad31e0b4671dfesewardj
2917c110443e39c0c63bb298689cad31e0b4671dfesewardj   The GNU General Public License is contained in the file COPYING.
3017c110443e39c0c63bb298689cad31e0b4671dfesewardj*/
3117c110443e39c0c63bb298689cad31e0b4671dfesewardj
328b68b64759254d514d98328c496cbd88cde4c9a5njn#if defined(VGO_linux)
338b68b64759254d514d98328c496cbd88cde4c9a5njn
3417c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_basics.h"
3517c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_vki.h"
3617c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_debuglog.h"
3717c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_libcbase.h"
3817c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_libcassert.h"
3917c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_libcfile.h"
4017c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_libcproc.h"
4117c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_libcprint.h"
4214c7cc5a5fbe9526329f058116f921988efe679esewardj#include "pub_core_xarray.h"
4317c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_clientstate.h"
4417c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_aspacemgr.h"
4517c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_mallocfree.h"
4617c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_machine.h"
4717c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_ume.h"
4817c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_options.h"
49d5c3f2839495d785ccf8e70c060eb2671507c192sewardj#include "pub_core_syscall.h"
5017c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_tooliface.h"       /* VG_TRACK */
5117c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_threadstate.h"     /* ThreadArchState */
5263ae69a7464f3cb383ea0b079f6ae5a8622a2c8fnjn#include "priv_initimg_pathscan.h"
5317c110443e39c0c63bb298689cad31e0b4671dfesewardj#include "pub_core_initimg.h"         /* self */
5417c110443e39c0c63bb298689cad31e0b4671dfesewardj
5517c110443e39c0c63bb298689cad31e0b4671dfesewardj/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
5617c110443e39c0c63bb298689cad31e0b4671dfesewardj#define _GNU_SOURCE
5717c110443e39c0c63bb298689cad31e0b4671dfesewardj#define _FILE_OFFSET_BITS 64
5817c110443e39c0c63bb298689cad31e0b4671dfesewardj/* This is for ELF types etc, and also the AT_ constants. */
5917c110443e39c0c63bb298689cad31e0b4671dfesewardj#include <elf.h>
6017c110443e39c0c63bb298689cad31e0b4671dfesewardj/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
6117c110443e39c0c63bb298689cad31e0b4671dfesewardj
6217c110443e39c0c63bb298689cad31e0b4671dfesewardj
6317c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
6417c110443e39c0c63bb298689cad31e0b4671dfesewardj/*=== Loading the client                                           ===*/
6517c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
6617c110443e39c0c63bb298689cad31e0b4671dfesewardj
6717c110443e39c0c63bb298689cad31e0b4671dfesewardj/* Load the client whose name is VG_(argv_the_exename). */
6817c110443e39c0c63bb298689cad31e0b4671dfesewardj
69a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughesstatic void load_client ( /*MOD*/ExeInfo* info,
7017c110443e39c0c63bb298689cad31e0b4671dfesewardj                          /*OUT*/Addr*    client_ip,
7117c110443e39c0c63bb298689cad31e0b4671dfesewardj			  /*OUT*/Addr*    client_toc)
7217c110443e39c0c63bb298689cad31e0b4671dfesewardj{
73c8b821428c9a8e63a6d055211963eae6eccc41c0florian   const HChar* exe_name;
7417c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int    ret;
7517c110443e39c0c63bb298689cad31e0b4671dfesewardj   SysRes res;
7617c110443e39c0c63bb298689cad31e0b4671dfesewardj
7717c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert( VG_(args_the_exename) != NULL);
7863ae69a7464f3cb383ea0b079f6ae5a8622a2c8fnjn   exe_name = ML_(find_executable)( VG_(args_the_exename) );
7917c110443e39c0c63bb298689cad31e0b4671dfesewardj
8017c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (!exe_name) {
8117c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
8217c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(exit)(127);      // 127 is Posix NOTFOUND
8317c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
8417c110443e39c0c63bb298689cad31e0b4671dfesewardj
8517c110443e39c0c63bb298689cad31e0b4671dfesewardj   ret = VG_(do_exec)(exe_name, info);
864c245e595b9f6300d3120408ca873f7115d9cc7dnjn   if (ret < 0) {
874c245e595b9f6300d3120408ca873f7115d9cc7dnjn      VG_(printf)("valgrind: could not execute '%s'\n", exe_name);
884c245e595b9f6300d3120408ca873f7115d9cc7dnjn      VG_(exit)(1);
894c245e595b9f6300d3120408ca873f7115d9cc7dnjn   }
9017c110443e39c0c63bb298689cad31e0b4671dfesewardj
9117c110443e39c0c63bb298689cad31e0b4671dfesewardj   // The client was successfully loaded!  Continue.
9217c110443e39c0c63bb298689cad31e0b4671dfesewardj
9317c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Get hold of a file descriptor which refers to the client
9417c110443e39c0c63bb298689cad31e0b4671dfesewardj      executable.  This is needed for attaching to GDB. */
9517c110443e39c0c63bb298689cad31e0b4671dfesewardj   res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
96cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (!sr_isError(res))
97cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      VG_(cl_exec_fd) = sr_Res(res);
9817c110443e39c0c63bb298689cad31e0b4671dfesewardj
9917c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Copy necessary bits of 'info' that were filled in */
10017c110443e39c0c63bb298689cad31e0b4671dfesewardj   *client_ip  = info->init_ip;
10117c110443e39c0c63bb298689cad31e0b4671dfesewardj   *client_toc = info->init_toc;
10217c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
10317c110443e39c0c63bb298689cad31e0b4671dfesewardj}
10417c110443e39c0c63bb298689cad31e0b4671dfesewardj
10517c110443e39c0c63bb298689cad31e0b4671dfesewardj
10617c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
10717c110443e39c0c63bb298689cad31e0b4671dfesewardj/*=== Setting up the client's environment                          ===*/
10817c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
10917c110443e39c0c63bb298689cad31e0b4671dfesewardj
11017c110443e39c0c63bb298689cad31e0b4671dfesewardj/* Prepare the client's environment.  This is basically a copy of our
11117c110443e39c0c63bb298689cad31e0b4671dfesewardj   environment, except:
11217c110443e39c0c63bb298689cad31e0b4671dfesewardj
1136bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn     LD_PRELOAD=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
1146bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn                ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
11517c110443e39c0c63bb298689cad31e0b4671dfesewardj                $LD_PRELOAD
11617c110443e39c0c63bb298689cad31e0b4671dfesewardj
11717c110443e39c0c63bb298689cad31e0b4671dfesewardj   If this is missing, then it is added.
11817c110443e39c0c63bb298689cad31e0b4671dfesewardj
11917c110443e39c0c63bb298689cad31e0b4671dfesewardj   Also, remove any binding for VALGRIND_LAUNCHER=.  The client should
12017c110443e39c0c63bb298689cad31e0b4671dfesewardj   not be able to see this.
12117c110443e39c0c63bb298689cad31e0b4671dfesewardj
12217c110443e39c0c63bb298689cad31e0b4671dfesewardj   If this needs to handle any more variables it should be hacked
12317c110443e39c0c63bb298689cad31e0b4671dfesewardj   into something table driven.  The copy is VG_(malloc)'d space.
12417c110443e39c0c63bb298689cad31e0b4671dfesewardj*/
12517c110443e39c0c63bb298689cad31e0b4671dfesewardjstatic HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
12617c110443e39c0c63bb298689cad31e0b4671dfesewardj{
12768790a73bcb290746a5b34c44538c3b2728eaaecflorian   vg_assert(origenv);
12868790a73bcb290746a5b34c44538c3b2728eaaecflorian   vg_assert(toolname);
12968790a73bcb290746a5b34c44538c3b2728eaaecflorian
130c8b821428c9a8e63a6d055211963eae6eccc41c0florian   const HChar* preload_core    = "vgpreload_core";
131c8b821428c9a8e63a6d055211963eae6eccc41c0florian   const HChar* ld_preload      = "LD_PRELOAD=";
132c8b821428c9a8e63a6d055211963eae6eccc41c0florian   const HChar* v_launcher      = VALGRIND_LAUNCHER "=";
13317c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int    ld_preload_len  = VG_(strlen)( ld_preload );
13417c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int    v_launcher_len  = VG_(strlen)( v_launcher );
13517c110443e39c0c63bb298689cad31e0b4671dfesewardj   Bool   ld_preload_done = False;
13617c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int    vglib_len       = VG_(strlen)(VG_(libdir));
137e9dd322e97711b2b399b0523163cf7e819425209sewardj   Bool   debug           = False;
13817c110443e39c0c63bb298689cad31e0b4671dfesewardj
13917c110443e39c0c63bb298689cad31e0b4671dfesewardj   HChar** cpp;
14017c110443e39c0c63bb298689cad31e0b4671dfesewardj   HChar** ret;
14117c110443e39c0c63bb298689cad31e0b4671dfesewardj   HChar*  preload_tool_path;
14217c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int     envc, i;
14317c110443e39c0c63bb298689cad31e0b4671dfesewardj
14417c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
14517c110443e39c0c63bb298689cad31e0b4671dfesewardj      paths.  We might not need the space for vgpreload_<tool>.so, but it
14617c110443e39c0c63bb298689cad31e0b4671dfesewardj      doesn't hurt to over-allocate briefly.  The 16s are just cautious
14717c110443e39c0c63bb298689cad31e0b4671dfesewardj      slop. */
14817c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int preload_core_path_len = vglib_len + sizeof(preload_core)
14917c110443e39c0c63bb298689cad31e0b4671dfesewardj                                         + sizeof(VG_PLATFORM) + 16;
15017c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname)
15117c110443e39c0c63bb298689cad31e0b4671dfesewardj                                         + sizeof(VG_PLATFORM) + 16;
15217c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int preload_string_len    = preload_core_path_len + preload_tool_path_len;
1539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   HChar* preload_string     = VG_(malloc)("initimg-linux.sce.1",
1549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                           preload_string_len);
1556bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn   /* Determine if there's a vgpreload_<tool>_<platform>.so file, and setup
15617c110443e39c0c63bb298689cad31e0b4671dfesewardj      preload_string. */
1579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   preload_tool_path = VG_(malloc)("initimg-linux.sce.2", preload_tool_path_len);
15817c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_(snprintf)(preload_tool_path, preload_tool_path_len,
1596bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn                 "%s/vgpreload_%s-%s.so", VG_(libdir), toolname, VG_PLATFORM);
16017c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
1616bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn      VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so:%s",
1626bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn                    VG_(libdir), preload_core, VG_PLATFORM, preload_tool_path);
16317c110443e39c0c63bb298689cad31e0b4671dfesewardj   } else {
1646bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn      VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so",
1656bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn                    VG_(libdir), preload_core, VG_PLATFORM);
16617c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
16717c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_(free)(preload_tool_path);
16817c110443e39c0c63bb298689cad31e0b4671dfesewardj
16917c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_(debugLog)(2, "initimg", "preload_string:\n");
17017c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_(debugLog)(2, "initimg", "  \"%s\"\n", preload_string);
17117c110443e39c0c63bb298689cad31e0b4671dfesewardj
17217c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Count the original size of the env */
173e9dd322e97711b2b399b0523163cf7e819425209sewardj   if (debug) VG_(printf)("\n\n");
17417c110443e39c0c63bb298689cad31e0b4671dfesewardj   envc = 0;
175e9dd322e97711b2b399b0523163cf7e819425209sewardj   for (cpp = origenv; cpp && *cpp; cpp++) {
17617c110443e39c0c63bb298689cad31e0b4671dfesewardj      envc++;
177e9dd322e97711b2b399b0523163cf7e819425209sewardj      if (debug) VG_(printf)("XXXXXXXXX: BEFORE %s\n", *cpp);
178e9dd322e97711b2b399b0523163cf7e819425209sewardj   }
17917c110443e39c0c63bb298689cad31e0b4671dfesewardj
18017c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Allocate a new space */
1819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ret = VG_(malloc) ("initimg-linux.sce.3",
1829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                      sizeof(HChar *) * (envc+1+1)); /* 1 new entry + NULL */
18317c110443e39c0c63bb298689cad31e0b4671dfesewardj
18417c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* copy it over */
185e9dd322e97711b2b399b0523163cf7e819425209sewardj   for (cpp = ret; *origenv; ) {
186e9dd322e97711b2b399b0523163cf7e819425209sewardj      if (debug) VG_(printf)("XXXXXXXXX: COPY   %s\n", *origenv);
18717c110443e39c0c63bb298689cad31e0b4671dfesewardj      *cpp++ = *origenv++;
188e9dd322e97711b2b399b0523163cf7e819425209sewardj   }
18917c110443e39c0c63bb298689cad31e0b4671dfesewardj   *cpp = NULL;
19017c110443e39c0c63bb298689cad31e0b4671dfesewardj
19117c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(envc == (cpp - ret));
19217c110443e39c0c63bb298689cad31e0b4671dfesewardj
19317c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Walk over the new environment, mashing as we go */
19417c110443e39c0c63bb298689cad31e0b4671dfesewardj   for (cpp = ret; cpp && *cpp; cpp++) {
19517c110443e39c0c63bb298689cad31e0b4671dfesewardj      if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) {
19617c110443e39c0c63bb298689cad31e0b4671dfesewardj         Int len = VG_(strlen)(*cpp) + preload_string_len;
1979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         HChar *cp = VG_(malloc)("initimg-linux.sce.4", len);
19817c110443e39c0c63bb298689cad31e0b4671dfesewardj
19917c110443e39c0c63bb298689cad31e0b4671dfesewardj         VG_(snprintf)(cp, len, "%s%s:%s",
20017c110443e39c0c63bb298689cad31e0b4671dfesewardj                       ld_preload, preload_string, (*cpp)+ld_preload_len);
20117c110443e39c0c63bb298689cad31e0b4671dfesewardj
20217c110443e39c0c63bb298689cad31e0b4671dfesewardj         *cpp = cp;
20317c110443e39c0c63bb298689cad31e0b4671dfesewardj
20417c110443e39c0c63bb298689cad31e0b4671dfesewardj         ld_preload_done = True;
20517c110443e39c0c63bb298689cad31e0b4671dfesewardj      }
206e9dd322e97711b2b399b0523163cf7e819425209sewardj      if (debug) VG_(printf)("XXXXXXXXX: MASH   %s\n", *cpp);
20717c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
20817c110443e39c0c63bb298689cad31e0b4671dfesewardj
20917c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Add the missing bits */
21017c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (!ld_preload_done) {
21117c110443e39c0c63bb298689cad31e0b4671dfesewardj      Int len = ld_preload_len + preload_string_len;
2129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      HChar *cp = VG_(malloc) ("initimg-linux.sce.5", len);
21317c110443e39c0c63bb298689cad31e0b4671dfesewardj
21417c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
21517c110443e39c0c63bb298689cad31e0b4671dfesewardj
21617c110443e39c0c63bb298689cad31e0b4671dfesewardj      ret[envc++] = cp;
217e9dd322e97711b2b399b0523163cf7e819425209sewardj      if (debug) VG_(printf)("XXXXXXXXX: ADD    %s\n", cp);
21817c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
21917c110443e39c0c63bb298689cad31e0b4671dfesewardj
22017c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* ret[0 .. envc-1] is live now. */
22117c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Find and remove a binding for VALGRIND_LAUNCHER. */
22217c110443e39c0c63bb298689cad31e0b4671dfesewardj   for (i = 0; i < envc; i++)
223a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      if (0 == VG_(memcmp)(ret[i], v_launcher, v_launcher_len))
22417c110443e39c0c63bb298689cad31e0b4671dfesewardj         break;
22517c110443e39c0c63bb298689cad31e0b4671dfesewardj
22617c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (i < envc) {
22717c110443e39c0c63bb298689cad31e0b4671dfesewardj      for (; i < envc-1; i++)
22817c110443e39c0c63bb298689cad31e0b4671dfesewardj         ret[i] = ret[i+1];
22917c110443e39c0c63bb298689cad31e0b4671dfesewardj      envc--;
23017c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
23117c110443e39c0c63bb298689cad31e0b4671dfesewardj
23217c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_(free)(preload_string);
23317c110443e39c0c63bb298689cad31e0b4671dfesewardj   ret[envc] = NULL;
23417c110443e39c0c63bb298689cad31e0b4671dfesewardj
235e9dd322e97711b2b399b0523163cf7e819425209sewardj   for (i = 0; i < envc; i++) {
236e9dd322e97711b2b399b0523163cf7e819425209sewardj      if (debug) VG_(printf)("XXXXXXXXX: FINAL  %s\n", ret[i]);
237e9dd322e97711b2b399b0523163cf7e819425209sewardj   }
238e9dd322e97711b2b399b0523163cf7e819425209sewardj
23917c110443e39c0c63bb298689cad31e0b4671dfesewardj   return ret;
24017c110443e39c0c63bb298689cad31e0b4671dfesewardj}
24117c110443e39c0c63bb298689cad31e0b4671dfesewardj
24217c110443e39c0c63bb298689cad31e0b4671dfesewardj
24317c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
24417c110443e39c0c63bb298689cad31e0b4671dfesewardj/*=== Setting up the client's stack                                ===*/
24517c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
24617c110443e39c0c63bb298689cad31e0b4671dfesewardj
24752b284b2fb907204dfae5a067e83eed98ea72dd2carll#ifndef AT_DCACHEBSIZE
24852b284b2fb907204dfae5a067e83eed98ea72dd2carll#define AT_DCACHEBSIZE		19
24952b284b2fb907204dfae5a067e83eed98ea72dd2carll#endif /* AT_DCACHEBSIZE */
25052b284b2fb907204dfae5a067e83eed98ea72dd2carll
25117c110443e39c0c63bb298689cad31e0b4671dfesewardj#ifndef AT_ICACHEBSIZE
25217c110443e39c0c63bb298689cad31e0b4671dfesewardj#define AT_ICACHEBSIZE		20
25317c110443e39c0c63bb298689cad31e0b4671dfesewardj#endif /* AT_ICACHEBSIZE */
25417c110443e39c0c63bb298689cad31e0b4671dfesewardj
25517c110443e39c0c63bb298689cad31e0b4671dfesewardj#ifndef AT_UCACHEBSIZE
25617c110443e39c0c63bb298689cad31e0b4671dfesewardj#define AT_UCACHEBSIZE		21
25717c110443e39c0c63bb298689cad31e0b4671dfesewardj#endif /* AT_UCACHEBSIZE */
25817c110443e39c0c63bb298689cad31e0b4671dfesewardj
259c880930fdabebbe59dd2c1f72f707cf95c796f1etom#ifndef AT_BASE_PLATFORM
260c880930fdabebbe59dd2c1f72f707cf95c796f1etom#define AT_BASE_PLATFORM	24
261c880930fdabebbe59dd2c1f72f707cf95c796f1etom#endif /* AT_BASE_PLATFORM */
262c880930fdabebbe59dd2c1f72f707cf95c796f1etom
2639c6533d2c47883f9e491a2a388c5503b3bf4c002tom#ifndef AT_RANDOM
2649c6533d2c47883f9e491a2a388c5503b3bf4c002tom#define AT_RANDOM		25
2659c6533d2c47883f9e491a2a388c5503b3bf4c002tom#endif /* AT_RANDOM */
2669c6533d2c47883f9e491a2a388c5503b3bf4c002tom
26752b284b2fb907204dfae5a067e83eed98ea72dd2carll#ifndef AT_HWCAP2
26852b284b2fb907204dfae5a067e83eed98ea72dd2carll#define AT_HWCAP2		26
26952b284b2fb907204dfae5a067e83eed98ea72dd2carll#endif /* AT_HWCAP2 */
27052b284b2fb907204dfae5a067e83eed98ea72dd2carll
27120a8a6125459a919a9561f8480b38f78f7c91fe9tom#ifndef AT_EXECFN
27220a8a6125459a919a9561f8480b38f78f7c91fe9tom#define AT_EXECFN		31
27320a8a6125459a919a9561f8480b38f78f7c91fe9tom#endif /* AT_EXECFN */
27420a8a6125459a919a9561f8480b38f78f7c91fe9tom
27517c110443e39c0c63bb298689cad31e0b4671dfesewardj#ifndef AT_SYSINFO
27617c110443e39c0c63bb298689cad31e0b4671dfesewardj#define AT_SYSINFO		32
27717c110443e39c0c63bb298689cad31e0b4671dfesewardj#endif /* AT_SYSINFO */
27817c110443e39c0c63bb298689cad31e0b4671dfesewardj
27917c110443e39c0c63bb298689cad31e0b4671dfesewardj#ifndef AT_SYSINFO_EHDR
28017c110443e39c0c63bb298689cad31e0b4671dfesewardj#define AT_SYSINFO_EHDR		33
28117c110443e39c0c63bb298689cad31e0b4671dfesewardj#endif /* AT_SYSINFO_EHDR */
28217c110443e39c0c63bb298689cad31e0b4671dfesewardj
28317c110443e39c0c63bb298689cad31e0b4671dfesewardj#ifndef AT_SECURE
28417c110443e39c0c63bb298689cad31e0b4671dfesewardj#define AT_SECURE 23   /* secure mode boolean */
28517c110443e39c0c63bb298689cad31e0b4671dfesewardj#endif	/* AT_SECURE */
28617c110443e39c0c63bb298689cad31e0b4671dfesewardj
28717c110443e39c0c63bb298689cad31e0b4671dfesewardj/* Add a string onto the string table, and return its address */
288c8b821428c9a8e63a6d055211963eae6eccc41c0florianstatic HChar *copy_str(HChar **tab, const HChar *str)
28917c110443e39c0c63bb298689cad31e0b4671dfesewardj{
290c8b821428c9a8e63a6d055211963eae6eccc41c0florian   HChar *cp = *tab;
291c8b821428c9a8e63a6d055211963eae6eccc41c0florian   HChar *orig = cp;
29217c110443e39c0c63bb298689cad31e0b4671dfesewardj
29317c110443e39c0c63bb298689cad31e0b4671dfesewardj   while(*str)
29417c110443e39c0c63bb298689cad31e0b4671dfesewardj      *cp++ = *str++;
29517c110443e39c0c63bb298689cad31e0b4671dfesewardj   *cp++ = '\0';
29617c110443e39c0c63bb298689cad31e0b4671dfesewardj
29717c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (0)
29817c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
29917c110443e39c0c63bb298689cad31e0b4671dfesewardj
30017c110443e39c0c63bb298689cad31e0b4671dfesewardj   *tab = cp;
30117c110443e39c0c63bb298689cad31e0b4671dfesewardj
30217c110443e39c0c63bb298689cad31e0b4671dfesewardj   return orig;
30317c110443e39c0c63bb298689cad31e0b4671dfesewardj}
30417c110443e39c0c63bb298689cad31e0b4671dfesewardj
30517c110443e39c0c63bb298689cad31e0b4671dfesewardj
30617c110443e39c0c63bb298689cad31e0b4671dfesewardj/* ----------------------------------------------------------------
30717c110443e39c0c63bb298689cad31e0b4671dfesewardj
30817c110443e39c0c63bb298689cad31e0b4671dfesewardj   This sets up the client's initial stack, containing the args,
30917c110443e39c0c63bb298689cad31e0b4671dfesewardj   environment and aux vector.
31017c110443e39c0c63bb298689cad31e0b4671dfesewardj
31117c110443e39c0c63bb298689cad31e0b4671dfesewardj   The format of the stack is:
31217c110443e39c0c63bb298689cad31e0b4671dfesewardj
31317c110443e39c0c63bb298689cad31e0b4671dfesewardj   higher address +-----------------+ <- clstack_end
31417c110443e39c0c63bb298689cad31e0b4671dfesewardj                  |                 |
31517c110443e39c0c63bb298689cad31e0b4671dfesewardj		  : string table    :
31617c110443e39c0c63bb298689cad31e0b4671dfesewardj		  |                 |
31717c110443e39c0c63bb298689cad31e0b4671dfesewardj		  +-----------------+
31817c110443e39c0c63bb298689cad31e0b4671dfesewardj		  | AT_NULL         |
31917c110443e39c0c63bb298689cad31e0b4671dfesewardj		  -                 -
32017c110443e39c0c63bb298689cad31e0b4671dfesewardj		  | auxv            |
32117c110443e39c0c63bb298689cad31e0b4671dfesewardj		  +-----------------+
32217c110443e39c0c63bb298689cad31e0b4671dfesewardj		  | NULL            |
32317c110443e39c0c63bb298689cad31e0b4671dfesewardj		  -                 -
32417c110443e39c0c63bb298689cad31e0b4671dfesewardj		  | envp            |
32517c110443e39c0c63bb298689cad31e0b4671dfesewardj		  +-----------------+
32617c110443e39c0c63bb298689cad31e0b4671dfesewardj		  | NULL            |
32717c110443e39c0c63bb298689cad31e0b4671dfesewardj		  -                 -
32817c110443e39c0c63bb298689cad31e0b4671dfesewardj		  | argv            |
32917c110443e39c0c63bb298689cad31e0b4671dfesewardj		  +-----------------+
33017c110443e39c0c63bb298689cad31e0b4671dfesewardj		  | argc            |
33117c110443e39c0c63bb298689cad31e0b4671dfesewardj   lower address  +-----------------+ <- sp
33217c110443e39c0c63bb298689cad31e0b4671dfesewardj                  | undefined       |
33317c110443e39c0c63bb298689cad31e0b4671dfesewardj		  :                 :
33417c110443e39c0c63bb298689cad31e0b4671dfesewardj
33517c110443e39c0c63bb298689cad31e0b4671dfesewardj   Allocate and create the initial client stack.  It is allocated down
33617c110443e39c0c63bb298689cad31e0b4671dfesewardj   from clstack_end, which was previously determined by the address
33717c110443e39c0c63bb298689cad31e0b4671dfesewardj   space manager.  The returned value is the SP value for the client.
33817c110443e39c0c63bb298689cad31e0b4671dfesewardj
33917c110443e39c0c63bb298689cad31e0b4671dfesewardj   The client's auxv is created by copying and modifying our own one.
34017c110443e39c0c63bb298689cad31e0b4671dfesewardj   As a side effect of scanning our own auxv, some important bits of
34117c110443e39c0c63bb298689cad31e0b4671dfesewardj   info are collected:
34217c110443e39c0c63bb298689cad31e0b4671dfesewardj
34317c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(cache_line_size_ppc32) // ppc32 only -- cache line size
34417c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(have_altivec_ppc32)    // ppc32 only -- is Altivec supported?
34517c110443e39c0c63bb298689cad31e0b4671dfesewardj
34617c110443e39c0c63bb298689cad31e0b4671dfesewardj   ---------------------------------------------------------------- */
34717c110443e39c0c63bb298689cad31e0b4671dfesewardj
34891772d140e9f918c25b9b20233d3673367b799dfnjnstruct auxv
34991772d140e9f918c25b9b20233d3673367b799dfnjn{
35091772d140e9f918c25b9b20233d3673367b799dfnjn   Word a_type;
35191772d140e9f918c25b9b20233d3673367b799dfnjn   union {
35291772d140e9f918c25b9b20233d3673367b799dfnjn      void *a_ptr;
35391772d140e9f918c25b9b20233d3673367b799dfnjn      Word a_val;
35491772d140e9f918c25b9b20233d3673367b799dfnjn   } u;
35591772d140e9f918c25b9b20233d3673367b799dfnjn};
35691772d140e9f918c25b9b20233d3673367b799dfnjn
35791772d140e9f918c25b9b20233d3673367b799dfnjnstatic
35891772d140e9f918c25b9b20233d3673367b799dfnjnstruct auxv *find_auxv(UWord* sp)
35991772d140e9f918c25b9b20233d3673367b799dfnjn{
36091772d140e9f918c25b9b20233d3673367b799dfnjn   sp++;                // skip argc (Nb: is word-sized, not int-sized!)
36191772d140e9f918c25b9b20233d3673367b799dfnjn
36291772d140e9f918c25b9b20233d3673367b799dfnjn   while (*sp != 0)     // skip argv
36391772d140e9f918c25b9b20233d3673367b799dfnjn      sp++;
36491772d140e9f918c25b9b20233d3673367b799dfnjn   sp++;
36591772d140e9f918c25b9b20233d3673367b799dfnjn
36691772d140e9f918c25b9b20233d3673367b799dfnjn   while (*sp != 0)     // skip env
36791772d140e9f918c25b9b20233d3673367b799dfnjn      sp++;
36891772d140e9f918c25b9b20233d3673367b799dfnjn   sp++;
36991772d140e9f918c25b9b20233d3673367b799dfnjn
370cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
37191772d140e9f918c25b9b20233d3673367b799dfnjn# if defined AT_IGNOREPPC
37291772d140e9f918c25b9b20233d3673367b799dfnjn   while (*sp == AT_IGNOREPPC)        // skip AT_IGNOREPPC entries
37391772d140e9f918c25b9b20233d3673367b799dfnjn      sp += 2;
37491772d140e9f918c25b9b20233d3673367b799dfnjn# endif
37591772d140e9f918c25b9b20233d3673367b799dfnjn#endif
37691772d140e9f918c25b9b20233d3673367b799dfnjn
37791772d140e9f918c25b9b20233d3673367b799dfnjn   return (struct auxv *)sp;
37891772d140e9f918c25b9b20233d3673367b799dfnjn}
37991772d140e9f918c25b9b20233d3673367b799dfnjn
38017c110443e39c0c63bb298689cad31e0b4671dfesewardjstatic
38117c110443e39c0c63bb298689cad31e0b4671dfesewardjAddr setup_client_stack( void*  init_sp,
382c8b821428c9a8e63a6d055211963eae6eccc41c0florian                         HChar** orig_envp,
38317c110443e39c0c63bb298689cad31e0b4671dfesewardj                         const ExeInfo* info,
38417c110443e39c0c63bb298689cad31e0b4671dfesewardj                         UInt** client_auxv,
38517c110443e39c0c63bb298689cad31e0b4671dfesewardj                         Addr   clstack_end,
38652b284b2fb907204dfae5a067e83eed98ea72dd2carll                         SizeT  clstack_max_size,
38752b284b2fb907204dfae5a067e83eed98ea72dd2carll                         const VexArchInfo* vex_archinfo )
38817c110443e39c0c63bb298689cad31e0b4671dfesewardj{
38952b284b2fb907204dfae5a067e83eed98ea72dd2carll  /* The HW configuration setting (hwcaps) of the target can be
39052b284b2fb907204dfae5a067e83eed98ea72dd2carll   * checked against the Vex settings of the host platform as given
39152b284b2fb907204dfae5a067e83eed98ea72dd2carll   * by the values in vex_archinfo.
39252b284b2fb907204dfae5a067e83eed98ea72dd2carll   */
39352b284b2fb907204dfae5a067e83eed98ea72dd2carll
39417c110443e39c0c63bb298689cad31e0b4671dfesewardj   SysRes res;
395c8b821428c9a8e63a6d055211963eae6eccc41c0florian   HChar **cpp;
396c8b821428c9a8e63a6d055211963eae6eccc41c0florian   HChar *strtab;		/* string table */
397c8b821428c9a8e63a6d055211963eae6eccc41c0florian   HChar *stringbase;
39817c110443e39c0c63bb298689cad31e0b4671dfesewardj   Addr *ptr;
39991772d140e9f918c25b9b20233d3673367b799dfnjn   struct auxv *auxv;
40091772d140e9f918c25b9b20233d3673367b799dfnjn   const struct auxv *orig_auxv;
40191772d140e9f918c25b9b20233d3673367b799dfnjn   const struct auxv *cauxv;
40217c110443e39c0c63bb298689cad31e0b4671dfesewardj   unsigned stringsize;		/* total size of strings in bytes */
40317c110443e39c0c63bb298689cad31e0b4671dfesewardj   unsigned auxsize;		/* total size of auxv in bytes */
40417c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int argc;			/* total argc */
40517c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int envc;			/* total number of env vars */
40617c110443e39c0c63bb298689cad31e0b4671dfesewardj   unsigned stacksize;		/* total client stack size */
40717c110443e39c0c63bb298689cad31e0b4671dfesewardj   Addr client_SP;	        /* client stack base (initial SP) */
40817c110443e39c0c63bb298689cad31e0b4671dfesewardj   Addr clstack_start;
40917c110443e39c0c63bb298689cad31e0b4671dfesewardj   Int i;
41017c110443e39c0c63bb298689cad31e0b4671dfesewardj
41117c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
41214c7cc5a5fbe9526329f058116f921988efe679esewardj   vg_assert( VG_(args_for_client) );
41317c110443e39c0c63bb298689cad31e0b4671dfesewardj
41417c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* use our own auxv as a prototype */
41591772d140e9f918c25b9b20233d3673367b799dfnjn   orig_auxv = find_auxv(init_sp);
41617c110443e39c0c63bb298689cad31e0b4671dfesewardj
41717c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* ==================== compute sizes ==================== */
41817c110443e39c0c63bb298689cad31e0b4671dfesewardj
41917c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* first of all, work out how big the client stack will be */
42017c110443e39c0c63bb298689cad31e0b4671dfesewardj   stringsize   = 0;
42117c110443e39c0c63bb298689cad31e0b4671dfesewardj
42217c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* paste on the extra args if the loader needs them (ie, the #!
42317c110443e39c0c63bb298689cad31e0b4671dfesewardj      interpreter and its argument) */
42417c110443e39c0c63bb298689cad31e0b4671dfesewardj   argc = 0;
42517c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (info->interp_name != NULL) {
42617c110443e39c0c63bb298689cad31e0b4671dfesewardj      argc++;
42717c110443e39c0c63bb298689cad31e0b4671dfesewardj      stringsize += VG_(strlen)(info->interp_name) + 1;
42817c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
42917c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (info->interp_args != NULL) {
43017c110443e39c0c63bb298689cad31e0b4671dfesewardj      argc++;
43117c110443e39c0c63bb298689cad31e0b4671dfesewardj      stringsize += VG_(strlen)(info->interp_args) + 1;
43217c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
43317c110443e39c0c63bb298689cad31e0b4671dfesewardj
43417c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* now scan the args we're given... */
435b16609bf952bf381154cb6cba87efc99c2c86a23florian   stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
43617c110443e39c0c63bb298689cad31e0b4671dfesewardj
43714c7cc5a5fbe9526329f058116f921988efe679esewardj   for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
43817c110443e39c0c63bb298689cad31e0b4671dfesewardj      argc++;
43914c7cc5a5fbe9526329f058116f921988efe679esewardj      stringsize += VG_(strlen)( * (HChar**)
44014c7cc5a5fbe9526329f058116f921988efe679esewardj                                   VG_(indexXA)( VG_(args_for_client), i ))
44114c7cc5a5fbe9526329f058116f921988efe679esewardj                    + 1;
44217c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
44317c110443e39c0c63bb298689cad31e0b4671dfesewardj
44417c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* ...and the environment */
44517c110443e39c0c63bb298689cad31e0b4671dfesewardj   envc = 0;
44617c110443e39c0c63bb298689cad31e0b4671dfesewardj   for (cpp = orig_envp; cpp && *cpp; cpp++) {
44717c110443e39c0c63bb298689cad31e0b4671dfesewardj      envc++;
44817c110443e39c0c63bb298689cad31e0b4671dfesewardj      stringsize += VG_(strlen)(*cpp) + 1;
44917c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
45017c110443e39c0c63bb298689cad31e0b4671dfesewardj
45117c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* now, how big is the auxv? */
45217c110443e39c0c63bb298689cad31e0b4671dfesewardj   auxsize = sizeof(*auxv);	/* there's always at least one entry: AT_NULL */
45317c110443e39c0c63bb298689cad31e0b4671dfesewardj   for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
454c880930fdabebbe59dd2c1f72f707cf95c796f1etom      if (cauxv->a_type == AT_PLATFORM ||
455c880930fdabebbe59dd2c1f72f707cf95c796f1etom          cauxv->a_type == AT_BASE_PLATFORM)
45617c110443e39c0c63bb298689cad31e0b4671dfesewardj	 stringsize += VG_(strlen)(cauxv->u.a_ptr) + 1;
4579c6533d2c47883f9e491a2a388c5503b3bf4c002tom      else if (cauxv->a_type == AT_RANDOM)
4589c6533d2c47883f9e491a2a388c5503b3bf4c002tom	 stringsize += 16;
459b16609bf952bf381154cb6cba87efc99c2c86a23florian      else if (cauxv->a_type == AT_EXECFN)
46020a8a6125459a919a9561f8480b38f78f7c91fe9tom	 stringsize += VG_(strlen)(VG_(args_the_exename)) + 1;
46117c110443e39c0c63bb298689cad31e0b4671dfesewardj      auxsize += sizeof(*cauxv);
46217c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
46317c110443e39c0c63bb298689cad31e0b4671dfesewardj
464cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
465cae0cc22b83ffb260ee8379e92099c5a701944cbcarll      || defined(VGP_ppc64le_linux)
46617c110443e39c0c63bb298689cad31e0b4671dfesewardj   auxsize += 2 * sizeof(*cauxv);
46717c110443e39c0c63bb298689cad31e0b4671dfesewardj#  endif
46817c110443e39c0c63bb298689cad31e0b4671dfesewardj
46917c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* OK, now we know how big the client stack is */
47017c110443e39c0c63bb298689cad31e0b4671dfesewardj   stacksize =
47117c110443e39c0c63bb298689cad31e0b4671dfesewardj      sizeof(Word) +                          /* argc */
472b16609bf952bf381154cb6cba87efc99c2c86a23florian      sizeof(HChar **) +                      /* argc[0] == exename */
473c8b821428c9a8e63a6d055211963eae6eccc41c0florian      sizeof(HChar **)*argc +                 /* argv */
474c8b821428c9a8e63a6d055211963eae6eccc41c0florian      sizeof(HChar **) +                      /* terminal NULL */
475c8b821428c9a8e63a6d055211963eae6eccc41c0florian      sizeof(HChar **)*envc +                 /* envp */
476c8b821428c9a8e63a6d055211963eae6eccc41c0florian      sizeof(HChar **) +                      /* terminal NULL */
47717c110443e39c0c63bb298689cad31e0b4671dfesewardj      auxsize +                               /* auxv */
47817c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_ROUNDUP(stringsize, sizeof(Word));   /* strings (aligned) */
47917c110443e39c0c63bb298689cad31e0b4671dfesewardj
480a5e06c36bf9d93461bc8c4351e960888020ea1c4florian   if (0) VG_(printf)("stacksize = %u\n", stacksize);
48117c110443e39c0c63bb298689cad31e0b4671dfesewardj
48217c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* client_SP is the client's stack pointer */
48317c110443e39c0c63bb298689cad31e0b4671dfesewardj   client_SP = clstack_end - stacksize;
48417c110443e39c0c63bb298689cad31e0b4671dfesewardj   client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */
48517c110443e39c0c63bb298689cad31e0b4671dfesewardj
48617c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* base of the string table (aligned) */
487c8b821428c9a8e63a6d055211963eae6eccc41c0florian   stringbase = strtab = (HChar *)clstack_end
48817c110443e39c0c63bb298689cad31e0b4671dfesewardj                         - VG_ROUNDUP(stringsize, sizeof(int));
48917c110443e39c0c63bb298689cad31e0b4671dfesewardj
49017c110443e39c0c63bb298689cad31e0b4671dfesewardj   clstack_start = VG_PGROUNDDN(client_SP);
49117c110443e39c0c63bb298689cad31e0b4671dfesewardj
49217c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* The max stack size */
49317c110443e39c0c63bb298689cad31e0b4671dfesewardj   clstack_max_size = VG_PGROUNDUP(clstack_max_size);
49417c110443e39c0c63bb298689cad31e0b4671dfesewardj
49517c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (0)
496a5e06c36bf9d93461bc8c4351e960888020ea1c4florian      VG_(printf)("stringsize=%u auxsize=%u stacksize=%u maxsize=0x%lx\n"
49717c110443e39c0c63bb298689cad31e0b4671dfesewardj                  "clstack_start %p\n"
49817c110443e39c0c63bb298689cad31e0b4671dfesewardj                  "clstack_end   %p\n",
499a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                  stringsize, auxsize, stacksize, clstack_max_size,
50017c110443e39c0c63bb298689cad31e0b4671dfesewardj                  (void*)clstack_start, (void*)clstack_end);
50117c110443e39c0c63bb298689cad31e0b4671dfesewardj
50217c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* ==================== allocate space ==================== */
50317c110443e39c0c63bb298689cad31e0b4671dfesewardj
50417c110443e39c0c63bb298689cad31e0b4671dfesewardj   { SizeT anon_size   = clstack_end - clstack_start + 1;
50517c110443e39c0c63bb298689cad31e0b4671dfesewardj     SizeT resvn_size  = clstack_max_size - anon_size;
50617c110443e39c0c63bb298689cad31e0b4671dfesewardj     Addr  anon_start  = clstack_start;
50717c110443e39c0c63bb298689cad31e0b4671dfesewardj     Addr  resvn_start = anon_start - resvn_size;
50817c110443e39c0c63bb298689cad31e0b4671dfesewardj     SizeT inner_HACK  = 0;
50917c110443e39c0c63bb298689cad31e0b4671dfesewardj     Bool  ok;
51017c110443e39c0c63bb298689cad31e0b4671dfesewardj
51117c110443e39c0c63bb298689cad31e0b4671dfesewardj     /* So far we've only accounted for space requirements down to the
51217c110443e39c0c63bb298689cad31e0b4671dfesewardj        stack pointer.  If this target's ABI requires a redzone below
51317c110443e39c0c63bb298689cad31e0b4671dfesewardj        the stack pointer, we need to allocate an extra page, to
51417c110443e39c0c63bb298689cad31e0b4671dfesewardj        handle the worst case in which the stack pointer is almost at
51517c110443e39c0c63bb298689cad31e0b4671dfesewardj        the bottom of a page, and so there is insufficient room left
51617c110443e39c0c63bb298689cad31e0b4671dfesewardj        over to put the redzone in.  In this case the simple thing to
51717c110443e39c0c63bb298689cad31e0b4671dfesewardj        do is allocate an extra page, by shrinking the reservation by
51817c110443e39c0c63bb298689cad31e0b4671dfesewardj        one page and growing the anonymous area by a corresponding
51917c110443e39c0c63bb298689cad31e0b4671dfesewardj        page. */
52017c110443e39c0c63bb298689cad31e0b4671dfesewardj     vg_assert(VG_STACK_REDZONE_SZB >= 0);
52117c110443e39c0c63bb298689cad31e0b4671dfesewardj     vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE);
52217c110443e39c0c63bb298689cad31e0b4671dfesewardj     if (VG_STACK_REDZONE_SZB > 0) {
52317c110443e39c0c63bb298689cad31e0b4671dfesewardj        vg_assert(resvn_size > VKI_PAGE_SIZE);
52417c110443e39c0c63bb298689cad31e0b4671dfesewardj        resvn_size -= VKI_PAGE_SIZE;
52517c110443e39c0c63bb298689cad31e0b4671dfesewardj        anon_start -= VKI_PAGE_SIZE;
52617c110443e39c0c63bb298689cad31e0b4671dfesewardj        anon_size += VKI_PAGE_SIZE;
52717c110443e39c0c63bb298689cad31e0b4671dfesewardj     }
52817c110443e39c0c63bb298689cad31e0b4671dfesewardj
52917c110443e39c0c63bb298689cad31e0b4671dfesewardj     vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
53017c110443e39c0c63bb298689cad31e0b4671dfesewardj     vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
53117c110443e39c0c63bb298689cad31e0b4671dfesewardj     vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
53217c110443e39c0c63bb298689cad31e0b4671dfesewardj     vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
53317c110443e39c0c63bb298689cad31e0b4671dfesewardj     vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
53417c110443e39c0c63bb298689cad31e0b4671dfesewardj
53517c110443e39c0c63bb298689cad31e0b4671dfesewardj#    ifdef ENABLE_INNER
53617c110443e39c0c63bb298689cad31e0b4671dfesewardj     inner_HACK = 1024*1024; // create 1M non-fault-extending stack
53717c110443e39c0c63bb298689cad31e0b4671dfesewardj#    endif
53817c110443e39c0c63bb298689cad31e0b4671dfesewardj
53917c110443e39c0c63bb298689cad31e0b4671dfesewardj     if (0)
540a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart        VG_(printf)("%#lx 0x%lx  %#lx 0x%lx\n",
54117c110443e39c0c63bb298689cad31e0b4671dfesewardj                    resvn_start, resvn_size, anon_start, anon_size);
54217c110443e39c0c63bb298689cad31e0b4671dfesewardj
54317c110443e39c0c63bb298689cad31e0b4671dfesewardj     /* Create a shrinkable reservation followed by an anonymous
54417c110443e39c0c63bb298689cad31e0b4671dfesewardj        segment.  Together these constitute a growdown stack. */
545d5c3f2839495d785ccf8e70c060eb2671507c192sewardj     res = VG_(mk_SysRes_Error)(0);
54617c110443e39c0c63bb298689cad31e0b4671dfesewardj     ok = VG_(am_create_reservation)(
54717c110443e39c0c63bb298689cad31e0b4671dfesewardj             resvn_start,
54817c110443e39c0c63bb298689cad31e0b4671dfesewardj             resvn_size -inner_HACK,
54917c110443e39c0c63bb298689cad31e0b4671dfesewardj             SmUpper,
55017c110443e39c0c63bb298689cad31e0b4671dfesewardj             anon_size +inner_HACK
55117c110443e39c0c63bb298689cad31e0b4671dfesewardj          );
552d5c3f2839495d785ccf8e70c060eb2671507c192sewardj     if (ok) {
553d5c3f2839495d785ccf8e70c060eb2671507c192sewardj        /* allocate a stack - mmap enough space for the stack */
554d5c3f2839495d785ccf8e70c060eb2671507c192sewardj        res = VG_(am_mmap_anon_fixed_client)(
555d5c3f2839495d785ccf8e70c060eb2671507c192sewardj                 anon_start -inner_HACK,
556d5c3f2839495d785ccf8e70c060eb2671507c192sewardj                 anon_size +inner_HACK,
55750d6d212fc8dfe63e2e83169fd8e12cf72ccfd1atom	         info->stack_prot
558d5c3f2839495d785ccf8e70c060eb2671507c192sewardj	      );
559d5c3f2839495d785ccf8e70c060eb2671507c192sewardj     }
560cda2f0fbda4c4b2644babc830244be8aed95de1dnjn     if ((!ok) || sr_isError(res)) {
561d5c3f2839495d785ccf8e70c060eb2671507c192sewardj        /* Allocation of the stack failed.  We have to stop. */
562d5c3f2839495d785ccf8e70c060eb2671507c192sewardj        VG_(printf)("valgrind: "
563d5c3f2839495d785ccf8e70c060eb2671507c192sewardj                    "I failed to allocate space for the application's stack.\n");
564d5c3f2839495d785ccf8e70c060eb2671507c192sewardj        VG_(printf)("valgrind: "
56595d86c091a218e904e912354efa4f952a9712e82sewardj                    "This may be the result of a very large --main-stacksize=\n");
566d5c3f2839495d785ccf8e70c060eb2671507c192sewardj        VG_(printf)("valgrind: setting.  Cannot continue.  Sorry.\n\n");
5679dc31561106f3f1b8057fdcdef94fa735a5f9c0aflorian        VG_(exit)(1);
568d5c3f2839495d785ccf8e70c060eb2671507c192sewardj     }
569d5c3f2839495d785ccf8e70c060eb2671507c192sewardj
57017c110443e39c0c63bb298689cad31e0b4671dfesewardj     vg_assert(ok);
571cda2f0fbda4c4b2644babc830244be8aed95de1dnjn     vg_assert(!sr_isError(res));
5724fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe
5734fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe     /* Record stack extent -- needed for stack-change code. */
57438a74d2cc4670e3eb559adff51a376cd6ec98005philippe     VG_(clstk_start_base) = anon_start -inner_HACK;
57538a74d2cc4670e3eb559adff51a376cd6ec98005philippe     VG_(clstk_end)  = VG_(clstk_start_base) + anon_size +inner_HACK -1;
5764fa3d371f8a70bb89e7f6bdf95011c05b3dbc7d4philippe
57717c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
57817c110443e39c0c63bb298689cad31e0b4671dfesewardj
57917c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* ==================== create client stack ==================== */
58017c110443e39c0c63bb298689cad31e0b4671dfesewardj
58117c110443e39c0c63bb298689cad31e0b4671dfesewardj   ptr = (Addr*)client_SP;
58217c110443e39c0c63bb298689cad31e0b4671dfesewardj
58317c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* --- client argc --- */
584b16609bf952bf381154cb6cba87efc99c2c86a23florian   *ptr++ = argc + 1;
58517c110443e39c0c63bb298689cad31e0b4671dfesewardj
58617c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* --- client argv --- */
587a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   if (info->interp_name)
58817c110443e39c0c63bb298689cad31e0b4671dfesewardj      *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
589a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   if (info->interp_args)
59017c110443e39c0c63bb298689cad31e0b4671dfesewardj      *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
59117c110443e39c0c63bb298689cad31e0b4671dfesewardj
592b16609bf952bf381154cb6cba87efc99c2c86a23florian   *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
59317c110443e39c0c63bb298689cad31e0b4671dfesewardj
59414c7cc5a5fbe9526329f058116f921988efe679esewardj   for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
59514c7cc5a5fbe9526329f058116f921988efe679esewardj      *ptr++ = (Addr)copy_str(
59614c7cc5a5fbe9526329f058116f921988efe679esewardj                       &strtab,
59714c7cc5a5fbe9526329f058116f921988efe679esewardj                       * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
59814c7cc5a5fbe9526329f058116f921988efe679esewardj                     );
59917c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
60017c110443e39c0c63bb298689cad31e0b4671dfesewardj   *ptr++ = 0;
60117c110443e39c0c63bb298689cad31e0b4671dfesewardj
60217c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* --- envp --- */
60319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   VG_(client_envp) = (HChar **)ptr;
60417c110443e39c0c63bb298689cad31e0b4671dfesewardj   for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
60517c110443e39c0c63bb298689cad31e0b4671dfesewardj      *ptr = (Addr)copy_str(&strtab, *cpp);
60617c110443e39c0c63bb298689cad31e0b4671dfesewardj   *ptr++ = 0;
60717c110443e39c0c63bb298689cad31e0b4671dfesewardj
60817c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* --- auxv --- */
60991772d140e9f918c25b9b20233d3673367b799dfnjn   auxv = (struct auxv *)ptr;
61017c110443e39c0c63bb298689cad31e0b4671dfesewardj   *client_auxv = (UInt *)auxv;
6112a31239309f89ea2d70c1bd29d2c1a7874e14812sewardj   VG_(client_auxv) = (UWord *)*client_auxv;
6122a31239309f89ea2d70c1bd29d2c1a7874e14812sewardj   // ??? According to 'man proc', auxv is a array of unsigned long
6132a31239309f89ea2d70c1bd29d2c1a7874e14812sewardj   // terminated by two zeros. Why is valgrind working with UInt ?
6142a31239309f89ea2d70c1bd29d2c1a7874e14812sewardj   // We do not take ULong* (as ULong 8 bytes on a 32 bits),
6152a31239309f89ea2d70c1bd29d2c1a7874e14812sewardj   // => we take UWord*
61617c110443e39c0c63bb298689cad31e0b4671dfesewardj
617cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
618cae0cc22b83ffb260ee8379e92099c5a701944cbcarll      || defined(VGP_ppc64le_linux)
61917c110443e39c0c63bb298689cad31e0b4671dfesewardj   auxv[0].a_type  = AT_IGNOREPPC;
62017c110443e39c0c63bb298689cad31e0b4671dfesewardj   auxv[0].u.a_val = AT_IGNOREPPC;
62117c110443e39c0c63bb298689cad31e0b4671dfesewardj   auxv[1].a_type  = AT_IGNOREPPC;
62217c110443e39c0c63bb298689cad31e0b4671dfesewardj   auxv[1].u.a_val = AT_IGNOREPPC;
62317c110443e39c0c63bb298689cad31e0b4671dfesewardj   auxv += 2;
62417c110443e39c0c63bb298689cad31e0b4671dfesewardj#  endif
62517c110443e39c0c63bb298689cad31e0b4671dfesewardj
62617c110443e39c0c63bb298689cad31e0b4671dfesewardj   for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
62717c110443e39c0c63bb298689cad31e0b4671dfesewardj
62817c110443e39c0c63bb298689cad31e0b4671dfesewardj      /* copy the entry... */
62917c110443e39c0c63bb298689cad31e0b4671dfesewardj      *auxv = *orig_auxv;
63017c110443e39c0c63bb298689cad31e0b4671dfesewardj
63117c110443e39c0c63bb298689cad31e0b4671dfesewardj      /* ...and fix up / examine the copy */
63217c110443e39c0c63bb298689cad31e0b4671dfesewardj      switch(auxv->a_type) {
63317c110443e39c0c63bb298689cad31e0b4671dfesewardj
63417c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_IGNORE:
63517c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_PHENT:
63617c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_PAGESZ:
63717c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_FLAGS:
63817c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_NOTELF:
63917c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_UID:
64017c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_EUID:
64117c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_GID:
64217c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_EGID:
64317c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_CLKTCK:
644a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes#        if !defined(VGPV_arm_linux_android) \
645a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes            && !defined(VGPV_x86_linux_android) \
646a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes            && !defined(VGPV_mips32_linux_android) \
647a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes            && !defined(VGPV_arm64_linux_android)
6486a1ec6bdd8ac1d79e721415e7f9e6247ece2ec8esewardj         case AT_FPUCW: /* missing on android */
649c19a5b043a10eb0477f34e66c614ca3a382edab7sewardj#        endif
65017c110443e39c0c63bb298689cad31e0b4671dfesewardj            /* All these are pointerless, so we don't need to do
65117c110443e39c0c63bb298689cad31e0b4671dfesewardj               anything about them. */
65217c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
65317c110443e39c0c63bb298689cad31e0b4671dfesewardj
65417c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_PHDR:
65517c110443e39c0c63bb298689cad31e0b4671dfesewardj            if (info->phdr == 0)
65617c110443e39c0c63bb298689cad31e0b4671dfesewardj               auxv->a_type = AT_IGNORE;
65717c110443e39c0c63bb298689cad31e0b4671dfesewardj            else
65817c110443e39c0c63bb298689cad31e0b4671dfesewardj               auxv->u.a_val = info->phdr;
65917c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
66017c110443e39c0c63bb298689cad31e0b4671dfesewardj
66117c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_PHNUM:
66217c110443e39c0c63bb298689cad31e0b4671dfesewardj            if (info->phdr == 0)
66317c110443e39c0c63bb298689cad31e0b4671dfesewardj               auxv->a_type = AT_IGNORE;
66417c110443e39c0c63bb298689cad31e0b4671dfesewardj            else
66517c110443e39c0c63bb298689cad31e0b4671dfesewardj               auxv->u.a_val = info->phnum;
66617c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
66717c110443e39c0c63bb298689cad31e0b4671dfesewardj
66817c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_BASE:
6693d24135101d712a59f9ec722e95d2a5670ea735etom            auxv->u.a_val = info->interp_offset;
67017c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
67117c110443e39c0c63bb298689cad31e0b4671dfesewardj
67217c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_PLATFORM:
673c880930fdabebbe59dd2c1f72f707cf95c796f1etom         case AT_BASE_PLATFORM:
67417c110443e39c0c63bb298689cad31e0b4671dfesewardj            /* points to a platform description string */
67517c110443e39c0c63bb298689cad31e0b4671dfesewardj            auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
67617c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
67717c110443e39c0c63bb298689cad31e0b4671dfesewardj
67817c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_ENTRY:
67917c110443e39c0c63bb298689cad31e0b4671dfesewardj            auxv->u.a_val = info->entry;
68017c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
68117c110443e39c0c63bb298689cad31e0b4671dfesewardj
68217c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_HWCAP:
683a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj#           if defined(VGP_arm_linux)
684a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj            { Bool has_neon = (auxv->u.a_val & VKI_HWCAP_NEON) > 0;
685a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj              VG_(debugLog)(2, "initimg",
686a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj                               "ARM has-neon from-auxv: %s\n",
687a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj                               has_neon ? "YES" : "NO");
688a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj              VG_(machine_arm_set_has_NEON)( has_neon );
689a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes#             define VKI_HWCAP_TLS 32768
690eeb0733e5659b10354d5f5daf69c3474d476705fphilippe              Bool has_tls = (auxv->u.a_val & VKI_HWCAP_TLS) > 0;
691a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes#             undef VKI_HWCAP_TLS
692eeb0733e5659b10354d5f5daf69c3474d476705fphilippe              VG_(debugLog)(2, "initimg",
693eeb0733e5659b10354d5f5daf69c3474d476705fphilippe                               "ARM has-tls from-auxv: %s\n",
694eeb0733e5659b10354d5f5daf69c3474d476705fphilippe                               has_tls ? "YES" : "NO");
695eeb0733e5659b10354d5f5daf69c3474d476705fphilippe              /* If real hw sets properly HWCAP_TLS, we might
696eeb0733e5659b10354d5f5daf69c3474d476705fphilippe                 use this info to decide to really execute set_tls syscall
697eeb0733e5659b10354d5f5daf69c3474d476705fphilippe                 in syswrap-arm-linux.c rather than to base this on
698eeb0733e5659b10354d5f5daf69c3474d476705fphilippe                 conditional compilation. */
699a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj            }
700416e4bb7c50cea52f911359da427db3912f87b21florian#           elif defined(VGP_s390x_linux)
701416e4bb7c50cea52f911359da427db3912f87b21florian            {
702416e4bb7c50cea52f911359da427db3912f87b21florian               /* Advertise hardware features "below" TE only.  TE and VXRS
703416e4bb7c50cea52f911359da427db3912f87b21florian                  (and anything above) are not supported by Valgrind. */
704416e4bb7c50cea52f911359da427db3912f87b21florian               auxv->u.a_val &= VKI_HWCAP_S390_TE - 1;
705416e4bb7c50cea52f911359da427db3912f87b21florian            }
706a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj#           endif
70717c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
70852b284b2fb907204dfae5a067e83eed98ea72dd2carll#        if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
7093b91f1779802a17344e1901f3b7c0271a22d3194carll         case AT_HWCAP2:  {
7103b91f1779802a17344e1901f3b7c0271a22d3194carll            Bool auxv_2_07, hw_caps_2_07;
7113b91f1779802a17344e1901f3b7c0271a22d3194carll	    /* The HWCAP2 field may contain an arch_2_07 entry that indicates
7123b91f1779802a17344e1901f3b7c0271a22d3194carll             * if the processor is compliant with the 2.07 ISA. (i.e. Power 8
7133b91f1779802a17344e1901f3b7c0271a22d3194carll             * or beyond).  The Valgrind vai.hwcaps value
7143b91f1779802a17344e1901f3b7c0271a22d3194carll             * (coregrind/m_machine.c) has the VEX_HWCAPS_PPC64_ISA2_07
71552b284b2fb907204dfae5a067e83eed98ea72dd2carll             * flag set so Valgrind knows about Power8.  Need to pass the
71652b284b2fb907204dfae5a067e83eed98ea72dd2carll             * HWCAP2 value along so the user level programs can detect that
71752b284b2fb907204dfae5a067e83eed98ea72dd2carll             * the processor supports ISA 2.07 and beyond.
71852b284b2fb907204dfae5a067e83eed98ea72dd2carll             */
71952b284b2fb907204dfae5a067e83eed98ea72dd2carll            /*  Power Architecture 64-Bit ELF V2 ABI Specification
72052b284b2fb907204dfae5a067e83eed98ea72dd2carll                July 21, 2014, version 1.0, Page 124
72152b284b2fb907204dfae5a067e83eed98ea72dd2carll                www-03.ibm.com/technologyconnect/tgcm/TGCMServlet.wss?alias=OpenPOWER&linkid=1n0000
72252b284b2fb907204dfae5a067e83eed98ea72dd2carll
72352b284b2fb907204dfae5a067e83eed98ea72dd2carll                AT_HWCAP2
72452b284b2fb907204dfae5a067e83eed98ea72dd2carll                The a_val member of this entry is a bit map of hardware
72552b284b2fb907204dfae5a067e83eed98ea72dd2carll                capabilities. Some bit mask values include:
72652b284b2fb907204dfae5a067e83eed98ea72dd2carll
72752b284b2fb907204dfae5a067e83eed98ea72dd2carll                PPC_FEATURE2_ARCH_2_07        0x80000000
72852b284b2fb907204dfae5a067e83eed98ea72dd2carll                PPC_FEATURE2_HAS_HTM          0x40000000
72952b284b2fb907204dfae5a067e83eed98ea72dd2carll                PPC_FEATURE2_HAS_DSCR         0x20000000
73052b284b2fb907204dfae5a067e83eed98ea72dd2carll                PPC_FEATURE2_HAS_EBB          0x10000000
73152b284b2fb907204dfae5a067e83eed98ea72dd2carll                PPC_FEATURE2_HAS_ISEL         0x08000000
73252b284b2fb907204dfae5a067e83eed98ea72dd2carll                PPC_FEATURE2_HAS_TAR          0x04000000
73352b284b2fb907204dfae5a067e83eed98ea72dd2carll                PPC_FEATURE2_HAS_VCRYPTO      0x02000000
73452b284b2fb907204dfae5a067e83eed98ea72dd2carll            */
7353b91f1779802a17344e1901f3b7c0271a22d3194carll            auxv_2_07 = (auxv->u.a_val & 0x80000000ULL) == 0x80000000ULL;
7363b91f1779802a17344e1901f3b7c0271a22d3194carll            hw_caps_2_07 = (vex_archinfo->hwcaps & VEX_HWCAPS_PPC64_ISA2_07)
7373b91f1779802a17344e1901f3b7c0271a22d3194carll               == VEX_HWCAPS_PPC64_ISA2_07;
7383b91f1779802a17344e1901f3b7c0271a22d3194carll
7393b91f1779802a17344e1901f3b7c0271a22d3194carll            /* Verify the PPC_FEATURE2_ARCH_2_07 setting in HWCAP2
7403b91f1779802a17344e1901f3b7c0271a22d3194carll	     * matches the setting in VEX HWCAPS.
7413b91f1779802a17344e1901f3b7c0271a22d3194carll	     */
7423b91f1779802a17344e1901f3b7c0271a22d3194carll            vg_assert(auxv_2_07 == hw_caps_2_07);
7433b91f1779802a17344e1901f3b7c0271a22d3194carll            }
74452b284b2fb907204dfae5a067e83eed98ea72dd2carll
74552b284b2fb907204dfae5a067e83eed98ea72dd2carll            break;
74652b284b2fb907204dfae5a067e83eed98ea72dd2carll#           endif
74717c110443e39c0c63bb298689cad31e0b4671dfesewardj
74817c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_ICACHEBSIZE:
74952b284b2fb907204dfae5a067e83eed98ea72dd2carll         case AT_DCACHEBSIZE:
75017c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_UCACHEBSIZE:
75117c110443e39c0c63bb298689cad31e0b4671dfesewardj#           if defined(VGP_ppc32_linux)
75217c110443e39c0c63bb298689cad31e0b4671dfesewardj            /* acquire cache info */
75317c110443e39c0c63bb298689cad31e0b4671dfesewardj            if (auxv->u.a_val > 0) {
75417c110443e39c0c63bb298689cad31e0b4671dfesewardj               VG_(machine_ppc32_set_clszB)( auxv->u.a_val );
75517c110443e39c0c63bb298689cad31e0b4671dfesewardj               VG_(debugLog)(2, "initimg",
7561a59a921dbfe75f7535d9dff6b76ea43a5ed961aflorian                                "PPC32 icache line size %u (type %u)\n",
75717c110443e39c0c63bb298689cad31e0b4671dfesewardj                                (UInt)auxv->u.a_val, (UInt)auxv->a_type );
75817c110443e39c0c63bb298689cad31e0b4671dfesewardj            }
759cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#           elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
76017c110443e39c0c63bb298689cad31e0b4671dfesewardj            /* acquire cache info */
76117c110443e39c0c63bb298689cad31e0b4671dfesewardj            if (auxv->u.a_val > 0) {
76217c110443e39c0c63bb298689cad31e0b4671dfesewardj               VG_(machine_ppc64_set_clszB)( auxv->u.a_val );
76317c110443e39c0c63bb298689cad31e0b4671dfesewardj               VG_(debugLog)(2, "initimg",
7641a59a921dbfe75f7535d9dff6b76ea43a5ed961aflorian                                "PPC64 icache line size %u (type %u)\n",
76517c110443e39c0c63bb298689cad31e0b4671dfesewardj                                (UInt)auxv->u.a_val, (UInt)auxv->a_type );
76617c110443e39c0c63bb298689cad31e0b4671dfesewardj            }
76717c110443e39c0c63bb298689cad31e0b4671dfesewardj#           endif
76817c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
76917c110443e39c0c63bb298689cad31e0b4671dfesewardj
770cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#        if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
771cae0cc22b83ffb260ee8379e92099c5a701944cbcarll            || defined(VGP_ppc64le_linux)
77217c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_IGNOREPPC:
77317c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
77417c110443e39c0c63bb298689cad31e0b4671dfesewardj#        endif
77517c110443e39c0c63bb298689cad31e0b4671dfesewardj
77617c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_SECURE:
77717c110443e39c0c63bb298689cad31e0b4671dfesewardj            /* If this is 1, then it means that this program is
77817c110443e39c0c63bb298689cad31e0b4671dfesewardj               running suid, and therefore the dynamic linker should
77917c110443e39c0c63bb298689cad31e0b4671dfesewardj               be careful about LD_PRELOAD, etc.  However, since
78017c110443e39c0c63bb298689cad31e0b4671dfesewardj               stage1 (the thing the kernel actually execve's) should
78117c110443e39c0c63bb298689cad31e0b4671dfesewardj               never be SUID, and we need LD_PRELOAD to work for the
78217c110443e39c0c63bb298689cad31e0b4671dfesewardj               client, we set AT_SECURE to 0. */
78317c110443e39c0c63bb298689cad31e0b4671dfesewardj            auxv->u.a_val = 0;
78417c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
78517c110443e39c0c63bb298689cad31e0b4671dfesewardj
78617c110443e39c0c63bb298689cad31e0b4671dfesewardj         case AT_SYSINFO:
7879bb8119b2ba66c8f93d0ba9e137332382990d6cdtom            /* Trash this, because we don't reproduce it */
7889bb8119b2ba66c8f93d0ba9e137332382990d6cdtom            auxv->a_type = AT_IGNORE;
7899bb8119b2ba66c8f93d0ba9e137332382990d6cdtom            break;
7909bb8119b2ba66c8f93d0ba9e137332382990d6cdtom
791cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#        if !defined(VGP_ppc32_linux) && !defined(VGP_ppc64be_linux) \
792ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            && !defined(VGP_ppc64le_linux) \
793ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            && !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux)
794d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj         case AT_SYSINFO_EHDR: {
79517c110443e39c0c63bb298689cad31e0b4671dfesewardj            /* Trash this, because we don't reproduce it */
796d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj            const NSegment* ehdrseg = VG_(am_find_nsegment)((Addr)auxv->u.a_ptr);
7979bb8119b2ba66c8f93d0ba9e137332382990d6cdtom            vg_assert(ehdrseg);
7989bb8119b2ba66c8f93d0ba9e137332382990d6cdtom            VG_(am_munmap_valgrind)(ehdrseg->start, ehdrseg->end - ehdrseg->start);
79917c110443e39c0c63bb298689cad31e0b4671dfesewardj            auxv->a_type = AT_IGNORE;
80017c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
801d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj         }
8029bb8119b2ba66c8f93d0ba9e137332382990d6cdtom#        endif
80317c110443e39c0c63bb298689cad31e0b4671dfesewardj
8049c6533d2c47883f9e491a2a388c5503b3bf4c002tom         case AT_RANDOM:
8059c6533d2c47883f9e491a2a388c5503b3bf4c002tom            /* points to 16 random bytes - we need to ensure this is
8069c6533d2c47883f9e491a2a388c5503b3bf4c002tom               propagated to the client as glibc will assume it is
8079c6533d2c47883f9e491a2a388c5503b3bf4c002tom               present if it is built for kernel 2.6.29 or later */
8089c6533d2c47883f9e491a2a388c5503b3bf4c002tom            auxv->u.a_ptr = strtab;
8099c6533d2c47883f9e491a2a388c5503b3bf4c002tom            VG_(memcpy)(strtab, orig_auxv->u.a_ptr, 16);
8109c6533d2c47883f9e491a2a388c5503b3bf4c002tom            strtab += 16;
8119c6533d2c47883f9e491a2a388c5503b3bf4c002tom            break;
8129c6533d2c47883f9e491a2a388c5503b3bf4c002tom
81320a8a6125459a919a9561f8480b38f78f7c91fe9tom         case AT_EXECFN:
81420a8a6125459a919a9561f8480b38f78f7c91fe9tom            /* points to the executable filename */
81520a8a6125459a919a9561f8480b38f78f7c91fe9tom            auxv->u.a_ptr = copy_str(&strtab, VG_(args_the_exename));
81620a8a6125459a919a9561f8480b38f78f7c91fe9tom            break;
81720a8a6125459a919a9561f8480b38f78f7c91fe9tom
81817c110443e39c0c63bb298689cad31e0b4671dfesewardj         default:
81917c110443e39c0c63bb298689cad31e0b4671dfesewardj            /* stomp out anything we don't know about */
82017c110443e39c0c63bb298689cad31e0b4671dfesewardj            VG_(debugLog)(2, "initimg",
821a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                             "stomping auxv entry %llu\n",
82217c110443e39c0c63bb298689cad31e0b4671dfesewardj                             (ULong)auxv->a_type);
82317c110443e39c0c63bb298689cad31e0b4671dfesewardj            auxv->a_type = AT_IGNORE;
82417c110443e39c0c63bb298689cad31e0b4671dfesewardj            break;
82517c110443e39c0c63bb298689cad31e0b4671dfesewardj      }
82617c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
82717c110443e39c0c63bb298689cad31e0b4671dfesewardj   *auxv = *orig_auxv;
82817c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(auxv->a_type == AT_NULL);
82917c110443e39c0c63bb298689cad31e0b4671dfesewardj
83017c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert((strtab-stringbase) == stringsize);
83117c110443e39c0c63bb298689cad31e0b4671dfesewardj
83217c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* client_SP is pointing at client's argc/argv */
83317c110443e39c0c63bb298689cad31e0b4671dfesewardj
834a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("startup SP = %#lx\n", client_SP);
83517c110443e39c0c63bb298689cad31e0b4671dfesewardj   return client_SP;
83617c110443e39c0c63bb298689cad31e0b4671dfesewardj}
83717c110443e39c0c63bb298689cad31e0b4671dfesewardj
83817c110443e39c0c63bb298689cad31e0b4671dfesewardj
83917c110443e39c0c63bb298689cad31e0b4671dfesewardj/* Allocate the client data segment.  It is an expandable anonymous
84017c110443e39c0c63bb298689cad31e0b4671dfesewardj   mapping abutting a shrinkable reservation of size max_dseg_size.
84117c110443e39c0c63bb298689cad31e0b4671dfesewardj   The data segment starts at VG_(brk_base), which is page-aligned,
84217c110443e39c0c63bb298689cad31e0b4671dfesewardj   and runs up to VG_(brk_limit), which isn't. */
84317c110443e39c0c63bb298689cad31e0b4671dfesewardj
84417c110443e39c0c63bb298689cad31e0b4671dfesewardjstatic void setup_client_dataseg ( SizeT max_size )
84517c110443e39c0c63bb298689cad31e0b4671dfesewardj{
84617c110443e39c0c63bb298689cad31e0b4671dfesewardj   Bool   ok;
84717c110443e39c0c63bb298689cad31e0b4671dfesewardj   SysRes sres;
84817c110443e39c0c63bb298689cad31e0b4671dfesewardj   Addr   anon_start  = VG_(brk_base);
84917c110443e39c0c63bb298689cad31e0b4671dfesewardj   SizeT  anon_size   = VKI_PAGE_SIZE;
85017c110443e39c0c63bb298689cad31e0b4671dfesewardj   Addr   resvn_start = anon_start + anon_size;
85117c110443e39c0c63bb298689cad31e0b4671dfesewardj   SizeT  resvn_size  = max_size - anon_size;
85217c110443e39c0c63bb298689cad31e0b4671dfesewardj
85317c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
85417c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
85517c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
85617c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
85717c110443e39c0c63bb298689cad31e0b4671dfesewardj
85817c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Because there's been no brk activity yet: */
85917c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(VG_(brk_base) == VG_(brk_limit));
86017c110443e39c0c63bb298689cad31e0b4671dfesewardj
86117c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Try to create the data seg and associated reservation where
86217c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(brk_base) says. */
86317c110443e39c0c63bb298689cad31e0b4671dfesewardj   ok = VG_(am_create_reservation)(
86417c110443e39c0c63bb298689cad31e0b4671dfesewardj           resvn_start,
86517c110443e39c0c63bb298689cad31e0b4671dfesewardj           resvn_size,
86617c110443e39c0c63bb298689cad31e0b4671dfesewardj           SmLower,
86717c110443e39c0c63bb298689cad31e0b4671dfesewardj           anon_size
86817c110443e39c0c63bb298689cad31e0b4671dfesewardj        );
86917c110443e39c0c63bb298689cad31e0b4671dfesewardj
87017c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (!ok) {
87117c110443e39c0c63bb298689cad31e0b4671dfesewardj      /* Hmm, that didn't work.  Well, let aspacem suggest an address
87217c110443e39c0c63bb298689cad31e0b4671dfesewardj         it likes better, and try again with that. */
87317c110443e39c0c63bb298689cad31e0b4671dfesewardj      anon_start = VG_(am_get_advisory_client_simple)
87417c110443e39c0c63bb298689cad31e0b4671dfesewardj                      ( 0/*floating*/, anon_size+resvn_size, &ok );
87517c110443e39c0c63bb298689cad31e0b4671dfesewardj      if (ok) {
87617c110443e39c0c63bb298689cad31e0b4671dfesewardj         resvn_start = anon_start + anon_size;
87717c110443e39c0c63bb298689cad31e0b4671dfesewardj         ok = VG_(am_create_reservation)(
87817c110443e39c0c63bb298689cad31e0b4671dfesewardj                 resvn_start,
87917c110443e39c0c63bb298689cad31e0b4671dfesewardj                 resvn_size,
88017c110443e39c0c63bb298689cad31e0b4671dfesewardj                 SmLower,
88117c110443e39c0c63bb298689cad31e0b4671dfesewardj                 anon_size
88217c110443e39c0c63bb298689cad31e0b4671dfesewardj              );
88317c110443e39c0c63bb298689cad31e0b4671dfesewardj         if (ok)
88417c110443e39c0c63bb298689cad31e0b4671dfesewardj            VG_(brk_base) = VG_(brk_limit) = anon_start;
88517c110443e39c0c63bb298689cad31e0b4671dfesewardj      }
88617c110443e39c0c63bb298689cad31e0b4671dfesewardj      /* that too might have failed, but if it has, we're hosed: there
88717c110443e39c0c63bb298689cad31e0b4671dfesewardj         is no Plan C. */
88817c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
88917c110443e39c0c63bb298689cad31e0b4671dfesewardj   vg_assert(ok);
89017c110443e39c0c63bb298689cad31e0b4671dfesewardj
89117c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* We make the data segment (heap) executable because LinuxThreads on
89217c110443e39c0c63bb298689cad31e0b4671dfesewardj      ppc32 creates trampolines in this area.  Also, on x86/Linux the data
89317c110443e39c0c63bb298689cad31e0b4671dfesewardj      segment is RWX natively, at least according to /proc/self/maps.
89417c110443e39c0c63bb298689cad31e0b4671dfesewardj      Also, having a non-executable data seg would kill any program which
89517c110443e39c0c63bb298689cad31e0b4671dfesewardj      tried to create code in the data seg and then run it. */
89617c110443e39c0c63bb298689cad31e0b4671dfesewardj   sres = VG_(am_mmap_anon_fixed_client)(
89717c110443e39c0c63bb298689cad31e0b4671dfesewardj             anon_start,
89817c110443e39c0c63bb298689cad31e0b4671dfesewardj             anon_size,
89917c110443e39c0c63bb298689cad31e0b4671dfesewardj             VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
90017c110443e39c0c63bb298689cad31e0b4671dfesewardj          );
901cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   vg_assert(!sr_isError(sres));
902cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   vg_assert(sr_Res(sres) == anon_start);
90317c110443e39c0c63bb298689cad31e0b4671dfesewardj}
90417c110443e39c0c63bb298689cad31e0b4671dfesewardj
90517c110443e39c0c63bb298689cad31e0b4671dfesewardj
90617c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
90717c110443e39c0c63bb298689cad31e0b4671dfesewardj/*=== TOP-LEVEL: VG_(setup_client_initial_image)                   ===*/
90817c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
90917c110443e39c0c63bb298689cad31e0b4671dfesewardj
91017c110443e39c0c63bb298689cad31e0b4671dfesewardj/* Create the client's initial memory image. */
91152b284b2fb907204dfae5a067e83eed98ea72dd2carllIIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii,
91252b284b2fb907204dfae5a067e83eed98ea72dd2carll                                          const VexArchInfo* vex_archinfo )
91317c110443e39c0c63bb298689cad31e0b4671dfesewardj{
914f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   ExeInfo info;
915f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   HChar** env = NULL;
916f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj
917a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   IIFinaliseImageInfo iifii = {
918a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      .clstack_max_size = 0,
919a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      .initial_client_SP = 0,
920a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      .initial_client_IP = 0,
921a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      .initial_client_TOC = 0,
922a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      .client_auxv = NULL,
923a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      .arch_elf_state = VKI_INIT_ARCH_ELF_STATE,
924a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   };
92517c110443e39c0c63bb298689cad31e0b4671dfesewardj
92617c110443e39c0c63bb298689cad31e0b4671dfesewardj   //--------------------------------------------------------------
92717c110443e39c0c63bb298689cad31e0b4671dfesewardj   // Load client executable, finding in $PATH if necessary
92817c110443e39c0c63bb298689cad31e0b4671dfesewardj   //   p: get_helprequest_and_toolname()  [for 'exec', 'need_help']
92917c110443e39c0c63bb298689cad31e0b4671dfesewardj   //   p: layout_remaining_space          [so there's space]
93017c110443e39c0c63bb298689cad31e0b4671dfesewardj   //--------------------------------------------------------------
93117c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_(debugLog)(1, "initimg", "Loading client\n");
93217c110443e39c0c63bb298689cad31e0b4671dfesewardj
93317c110443e39c0c63bb298689cad31e0b4671dfesewardj   if (VG_(args_the_exename) == NULL)
93417c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(err_missing_prog)();
93517c110443e39c0c63bb298689cad31e0b4671dfesewardj
936a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   VG_(memset)(&info, 0, sizeof(info));
937a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   info.arch_elf_state = &iifii.arch_elf_state;
938a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
939f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   load_client(&info, &iifii.initial_client_IP, &iifii.initial_client_TOC);
94017c110443e39c0c63bb298689cad31e0b4671dfesewardj
94117c110443e39c0c63bb298689cad31e0b4671dfesewardj   //--------------------------------------------------------------
94217c110443e39c0c63bb298689cad31e0b4671dfesewardj   // Set up client's environment
94317c110443e39c0c63bb298689cad31e0b4671dfesewardj   //   p: set-libdir                   [for VG_(libdir)]
94417c110443e39c0c63bb298689cad31e0b4671dfesewardj   //   p: get_helprequest_and_toolname [for toolname]
94517c110443e39c0c63bb298689cad31e0b4671dfesewardj   //--------------------------------------------------------------
94617c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_(debugLog)(1, "initimg", "Setup client env\n");
947f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   env = setup_client_env(iicii.envp, iicii.toolname);
94817c110443e39c0c63bb298689cad31e0b4671dfesewardj
94917c110443e39c0c63bb298689cad31e0b4671dfesewardj   //--------------------------------------------------------------
95017c110443e39c0c63bb298689cad31e0b4671dfesewardj   // Setup client stack, eip, and VG_(client_arg[cv])
95117c110443e39c0c63bb298689cad31e0b4671dfesewardj   //   p: load_client()     [for 'info']
95217c110443e39c0c63bb298689cad31e0b4671dfesewardj   //   p: fix_environment() [for 'env']
95317c110443e39c0c63bb298689cad31e0b4671dfesewardj   //--------------------------------------------------------------
95417c110443e39c0c63bb298689cad31e0b4671dfesewardj   {
9555bdfbd29e26bc536c0779ec2e6b85bbb0ebd622csewardj      /* When allocating space for the client stack on Linux, take
95695d86c091a218e904e912354efa4f952a9712e82sewardj         notice of the --main-stacksize value.  This makes it possible
9575bdfbd29e26bc536c0779ec2e6b85bbb0ebd622csewardj         to run programs with very large (primary) stack requirements
95895d86c091a218e904e912354efa4f952a9712e82sewardj         simply by specifying --main-stacksize. */
95995d86c091a218e904e912354efa4f952a9712e82sewardj      /* Logic is as follows:
96095d86c091a218e904e912354efa4f952a9712e82sewardj         - by default, use the client's current stack rlimit
96195d86c091a218e904e912354efa4f952a9712e82sewardj         - if that exceeds 16M, clamp to 16M
96295d86c091a218e904e912354efa4f952a9712e82sewardj         - if a larger --main-stacksize value is specified, use that instead
96395d86c091a218e904e912354efa4f952a9712e82sewardj         - in all situations, the minimum allowed stack size is 1M
96495d86c091a218e904e912354efa4f952a9712e82sewardj      */
965f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj      void* init_sp = iicii.argv - 1;
96617c110443e39c0c63bb298689cad31e0b4671dfesewardj      SizeT m1  = 1024 * 1024;
96717c110443e39c0c63bb298689cad31e0b4671dfesewardj      SizeT m16 = 16 * m1;
96895d86c091a218e904e912354efa4f952a9712e82sewardj      SizeT szB = (SizeT)VG_(client_rlimit_stack).rlim_cur;
96995d86c091a218e904e912354efa4f952a9712e82sewardj      if (szB < m1) szB = m1;
97095d86c091a218e904e912354efa4f952a9712e82sewardj      if (szB > m16) szB = m16;
97195d86c091a218e904e912354efa4f952a9712e82sewardj      if (VG_(clo_main_stacksize) > 0) szB = VG_(clo_main_stacksize);
97295d86c091a218e904e912354efa4f952a9712e82sewardj      if (szB < m1) szB = m1;
97395d86c091a218e904e912354efa4f952a9712e82sewardj      szB = VG_PGROUNDUP(szB);
97495d86c091a218e904e912354efa4f952a9712e82sewardj      VG_(debugLog)(1, "initimg",
975a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                       "Setup client stack: size will be %lu\n", szB);
97695d86c091a218e904e912354efa4f952a9712e82sewardj
97795d86c091a218e904e912354efa4f952a9712e82sewardj      iifii.clstack_max_size = szB;
97817c110443e39c0c63bb298689cad31e0b4671dfesewardj
979f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj      iifii.initial_client_SP
98017c110443e39c0c63bb298689cad31e0b4671dfesewardj         = setup_client_stack( init_sp, env,
981f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj                               &info, &iifii.client_auxv,
98252b284b2fb907204dfae5a067e83eed98ea72dd2carll                               iicii.clstack_end, iifii.clstack_max_size,
98352b284b2fb907204dfae5a067e83eed98ea72dd2carll                               vex_archinfo );
98417c110443e39c0c63bb298689cad31e0b4671dfesewardj
98517c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(free)(env);
98617c110443e39c0c63bb298689cad31e0b4671dfesewardj
98717c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(debugLog)(2, "initimg",
98817c110443e39c0c63bb298689cad31e0b4671dfesewardj                       "Client info: "
9895bdfbd29e26bc536c0779ec2e6b85bbb0ebd622csewardj                       "initial_IP=%p initial_TOC=%p brk_base=%p\n",
990f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj                       (void*)(iifii.initial_client_IP),
991f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj                       (void*)(iifii.initial_client_TOC),
99217c110443e39c0c63bb298689cad31e0b4671dfesewardj                       (void*)VG_(brk_base) );
9935bdfbd29e26bc536c0779ec2e6b85bbb0ebd622csewardj      VG_(debugLog)(2, "initimg",
9945bdfbd29e26bc536c0779ec2e6b85bbb0ebd622csewardj                       "Client info: "
995a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                       "initial_SP=%p max_stack_size=%lu\n",
9965bdfbd29e26bc536c0779ec2e6b85bbb0ebd622csewardj                       (void*)(iifii.initial_client_SP),
997a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                       iifii.clstack_max_size );
99817c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
99917c110443e39c0c63bb298689cad31e0b4671dfesewardj
100017c110443e39c0c63bb298689cad31e0b4671dfesewardj   //--------------------------------------------------------------
100117c110443e39c0c63bb298689cad31e0b4671dfesewardj   // Setup client data (brk) segment.  Initially a 1-page segment
100217c110443e39c0c63bb298689cad31e0b4671dfesewardj   // which abuts a shrinkable reservation.
100317c110443e39c0c63bb298689cad31e0b4671dfesewardj   //     p: load_client()     [for 'info' and hence VG_(brk_base)]
100417c110443e39c0c63bb298689cad31e0b4671dfesewardj   //--------------------------------------------------------------
100517c110443e39c0c63bb298689cad31e0b4671dfesewardj   {
100617c110443e39c0c63bb298689cad31e0b4671dfesewardj      SizeT m1 = 1024 * 1024;
100717c110443e39c0c63bb298689cad31e0b4671dfesewardj      SizeT m8 = 8 * m1;
100817c110443e39c0c63bb298689cad31e0b4671dfesewardj      SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
100917c110443e39c0c63bb298689cad31e0b4671dfesewardj      VG_(debugLog)(1, "initimg", "Setup client data (brk) segment\n");
101017c110443e39c0c63bb298689cad31e0b4671dfesewardj      if (dseg_max_size < m1) dseg_max_size = m1;
101117c110443e39c0c63bb298689cad31e0b4671dfesewardj      if (dseg_max_size > m8) dseg_max_size = m8;
101217c110443e39c0c63bb298689cad31e0b4671dfesewardj      dseg_max_size = VG_PGROUNDUP(dseg_max_size);
101317c110443e39c0c63bb298689cad31e0b4671dfesewardj
101417c110443e39c0c63bb298689cad31e0b4671dfesewardj      setup_client_dataseg( dseg_max_size );
101517c110443e39c0c63bb298689cad31e0b4671dfesewardj   }
101617c110443e39c0c63bb298689cad31e0b4671dfesewardj
1017a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   VG_(free)(info.interp_name); info.interp_name = NULL;
1018a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   VG_(free)(info.interp_args); info.interp_args = NULL;
1019f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   return iifii;
102017c110443e39c0c63bb298689cad31e0b4671dfesewardj}
102117c110443e39c0c63bb298689cad31e0b4671dfesewardj
102217c110443e39c0c63bb298689cad31e0b4671dfesewardj
102317c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
102417c110443e39c0c63bb298689cad31e0b4671dfesewardj/*=== TOP-LEVEL: VG_(finalise_thread1state)                        ===*/
102517c110443e39c0c63bb298689cad31e0b4671dfesewardj/*====================================================================*/
102617c110443e39c0c63bb298689cad31e0b4671dfesewardj
1027f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj/* Just before starting the client, we may need to make final
1028f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   adjustments to its initial image.  Also we need to set up the VEX
1029f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   guest state for thread 1 (the root thread) and copy in essential
1030f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   starting values.  This is handed the IIFinaliseImageInfo created by
1031f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   VG_(ii_create_image).
1032f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj*/
1033f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardjvoid VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
103417c110443e39c0c63bb298689cad31e0b4671dfesewardj{
1035f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   ThreadArchState* arch = &VG_(threads)[1].arch;
1036f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj
103717c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* On Linux we get client_{ip/sp/toc}, and start the client with
103817c110443e39c0c63bb298689cad31e0b4671dfesewardj      all other registers zeroed. */
103917c110443e39c0c63bb298689cad31e0b4671dfesewardj
104017c110443e39c0c63bb298689cad31e0b4671dfesewardj#  if defined(VGP_x86_linux)
1041737548c7409e5d46b72a914ae1dc6d1a48199d25florian   vg_assert(0 == sizeof(VexGuestX86State) % LibVEX_GUEST_STATE_ALIGN);
104217c110443e39c0c63bb298689cad31e0b4671dfesewardj
104317c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Zero out the initial state, and set up the simulated FPU in a
104417c110443e39c0c63bb298689cad31e0b4671dfesewardj      sane way. */
104517c110443e39c0c63bb298689cad31e0b4671dfesewardj   LibVEX_GuestX86_initialise(&arch->vex);
104617c110443e39c0c63bb298689cad31e0b4671dfesewardj
10477cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Zero out the shadow areas. */
10487cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State));
10497cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State));
105017c110443e39c0c63bb298689cad31e0b4671dfesewardj
105117c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Put essential stuff into the new state. */
1052f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_ESP = iifii.initial_client_SP;
1053f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_EIP = iifii.initial_client_IP;
105417c110443e39c0c63bb298689cad31e0b4671dfesewardj
105517c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* initialise %cs, %ds and %ss to point at the operating systems
105690ffbe3cc96002ab396de87fb78930f6059ece82sewardj      default code, data and stack segments.  Also %es (see #291253). */
105717c110443e39c0c63bb298689cad31e0b4671dfesewardj   asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
105817c110443e39c0c63bb298689cad31e0b4671dfesewardj   asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
105917c110443e39c0c63bb298689cad31e0b4671dfesewardj   asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
106090ffbe3cc96002ab396de87fb78930f6059ece82sewardj   asm volatile("movw %%es, %0" : : "m" (arch->vex.guest_ES));
106117c110443e39c0c63bb298689cad31e0b4671dfesewardj
106217c110443e39c0c63bb298689cad31e0b4671dfesewardj#  elif defined(VGP_amd64_linux)
1063737548c7409e5d46b72a914ae1dc6d1a48199d25florian   vg_assert(0 == sizeof(VexGuestAMD64State) % LibVEX_GUEST_STATE_ALIGN);
106417c110443e39c0c63bb298689cad31e0b4671dfesewardj
106517c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Zero out the initial state, and set up the simulated FPU in a
106617c110443e39c0c63bb298689cad31e0b4671dfesewardj      sane way. */
106717c110443e39c0c63bb298689cad31e0b4671dfesewardj   LibVEX_GuestAMD64_initialise(&arch->vex);
106817c110443e39c0c63bb298689cad31e0b4671dfesewardj
10697cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Zero out the shadow areas. */
10707cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State));
10717cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State));
107217c110443e39c0c63bb298689cad31e0b4671dfesewardj
107317c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Put essential stuff into the new state. */
1074f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_RSP = iifii.initial_client_SP;
1075f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_RIP = iifii.initial_client_IP;
107617c110443e39c0c63bb298689cad31e0b4671dfesewardj
107717c110443e39c0c63bb298689cad31e0b4671dfesewardj#  elif defined(VGP_ppc32_linux)
1078737548c7409e5d46b72a914ae1dc6d1a48199d25florian   vg_assert(0 == sizeof(VexGuestPPC32State) % LibVEX_GUEST_STATE_ALIGN);
107917c110443e39c0c63bb298689cad31e0b4671dfesewardj
108017c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Zero out the initial state, and set up the simulated FPU in a
108117c110443e39c0c63bb298689cad31e0b4671dfesewardj      sane way. */
108217c110443e39c0c63bb298689cad31e0b4671dfesewardj   LibVEX_GuestPPC32_initialise(&arch->vex);
108317c110443e39c0c63bb298689cad31e0b4671dfesewardj
10847cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Zero out the shadow areas. */
10857cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestPPC32State));
10867cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestPPC32State));
108717c110443e39c0c63bb298689cad31e0b4671dfesewardj
108817c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Put essential stuff into the new state. */
1089f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_GPR1 = iifii.initial_client_SP;
1090f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_CIA  = iifii.initial_client_IP;
109117c110443e39c0c63bb298689cad31e0b4671dfesewardj
1092cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1093737548c7409e5d46b72a914ae1dc6d1a48199d25florian   vg_assert(0 == sizeof(VexGuestPPC64State) % LibVEX_GUEST_STATE_ALIGN);
109417c110443e39c0c63bb298689cad31e0b4671dfesewardj
109517c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Zero out the initial state, and set up the simulated FPU in a
109617c110443e39c0c63bb298689cad31e0b4671dfesewardj      sane way. */
109717c110443e39c0c63bb298689cad31e0b4671dfesewardj   LibVEX_GuestPPC64_initialise(&arch->vex);
109817c110443e39c0c63bb298689cad31e0b4671dfesewardj
10997cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Zero out the shadow areas. */
11007cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestPPC64State));
11017cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestPPC64State));
110217c110443e39c0c63bb298689cad31e0b4671dfesewardj
110317c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Put essential stuff into the new state. */
1104f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_GPR1 = iifii.initial_client_SP;
1105f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_GPR2 = iifii.initial_client_TOC;
1106f9d2f9b5ec3b8febc8465c05e90c8a5f6de3d6a4sewardj   arch->vex.guest_CIA  = iifii.initial_client_IP;
1107582d58245637ab05272d89fb94b12fd0f18fa0f8carll#if defined(VGP_ppc64le_linux)
1108582d58245637ab05272d89fb94b12fd0f18fa0f8carll   arch->vex.guest_GPR12 = iifii.initial_client_IP;
1109582d58245637ab05272d89fb94b12fd0f18fa0f8carll#endif
111017c110443e39c0c63bb298689cad31e0b4671dfesewardj
1111f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm_linux)
111259570ffbe31930ab4d678754daaeec0715117a3dsewardj   /* Zero out the initial state, and set up the simulated FPU in a
111359570ffbe31930ab4d678754daaeec0715117a3dsewardj      sane way. */
111459570ffbe31930ab4d678754daaeec0715117a3dsewardj   LibVEX_GuestARM_initialise(&arch->vex);
111559570ffbe31930ab4d678754daaeec0715117a3dsewardj
111659570ffbe31930ab4d678754daaeec0715117a3dsewardj   /* Zero out the shadow areas. */
111759570ffbe31930ab4d678754daaeec0715117a3dsewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestARMState));
111859570ffbe31930ab4d678754daaeec0715117a3dsewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestARMState));
111959570ffbe31930ab4d678754daaeec0715117a3dsewardj
11209dcfdffec13e259386e088f9be86ea8b8e2756c0sewardj   arch->vex.guest_R13  = iifii.initial_client_SP;
11219dcfdffec13e259386e088f9be86ea8b8e2756c0sewardj   arch->vex.guest_R15T = iifii.initial_client_IP;
112259570ffbe31930ab4d678754daaeec0715117a3dsewardj
112359570ffbe31930ab4d678754daaeec0715117a3dsewardj   /* This is just EABI stuff. */
112459570ffbe31930ab4d678754daaeec0715117a3dsewardj   // FIXME jrs: what's this for?
112559570ffbe31930ab4d678754daaeec0715117a3dsewardj   arch->vex.guest_R1 =  iifii.initial_client_SP;
112659570ffbe31930ab4d678754daaeec0715117a3dsewardj
1127f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
1128f0c1250e324f6684757c6a15545366447ef1d64fsewardj   /* Zero out the initial state. */
1129f0c1250e324f6684757c6a15545366447ef1d64fsewardj   LibVEX_GuestARM64_initialise(&arch->vex);
1130f0c1250e324f6684757c6a15545366447ef1d64fsewardj
1131f0c1250e324f6684757c6a15545366447ef1d64fsewardj   /* Zero out the shadow areas. */
1132f0c1250e324f6684757c6a15545366447ef1d64fsewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestARM64State));
1133f0c1250e324f6684757c6a15545366447ef1d64fsewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestARM64State));
1134f0c1250e324f6684757c6a15545366447ef1d64fsewardj
11350345188cc1524a809b8d7fe8785e1da098d9cbe4sewardj   arch->vex.guest_XSP = iifii.initial_client_SP;
11360345188cc1524a809b8d7fe8785e1da098d9cbe4sewardj   arch->vex.guest_PC  = iifii.initial_client_IP;
1137f0c1250e324f6684757c6a15545366447ef1d64fsewardj
1138b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGP_s390x_linux)
1139737548c7409e5d46b72a914ae1dc6d1a48199d25florian   vg_assert(0 == sizeof(VexGuestS390XState) % LibVEX_GUEST_STATE_ALIGN);
1140b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
1141b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   /* Zero out the initial state. This also sets the guest_fpc to 0, which
1142b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      is also done by the kernel for the fpc during execve. */
1143b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   LibVEX_GuestS390X_initialise(&arch->vex);
1144b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
1145ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   /* Mark all registers as undefined ... */
1146ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   VG_(memset)(&arch->vex_shadow1, 0xFF, sizeof(VexGuestS390XState));
1147ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   VG_(memset)(&arch->vex_shadow2, 0x00, sizeof(VexGuestS390XState));
1148ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   /* ... except SP, FPC, and IA */
11497e5a9c29450b41cba63ac04b9c027d3b97b367eccborntra   arch->vex_shadow1.guest_SP = 0;
11507e5a9c29450b41cba63ac04b9c027d3b97b367eccborntra   arch->vex_shadow1.guest_fpc = 0;
11517e5a9c29450b41cba63ac04b9c027d3b97b367eccborntra   arch->vex_shadow1.guest_IA = 0;
1152b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
1153b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   /* Put essential stuff into the new state. */
1154b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   arch->vex.guest_SP = iifii.initial_client_SP;
1155b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   arch->vex.guest_IA = iifii.initial_client_IP;
1156ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   /* See sys_execve in <linux>/arch/s390/kernel/process.c */
1157ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   arch->vex.guest_fpc = 0;
1158ccb843b2ba2c176708bfa1764ca8e4db31722e90florian
1159ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   /* Tell the tool about the registers we just wrote */
1160ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_STACK_PTR, 8);
1161ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_FPC_REG,   4);
1162ccb843b2ba2c176708bfa1764ca8e4db31722e90florian   VG_TRACK(post_reg_write, Vg_CoreStartup, /*tid*/1, VG_O_INSTR_PTR, 8);
116381de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian
116481de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian   /* At the end of this function there is code to mark all guest state
116581de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian      registers as defined. For s390 that would be wrong, because the ABI
116681de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian      says that all registers except SP, IA, and FPC are undefined upon
116781de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian      process startup. */
116881de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian#define PRECISE_GUEST_REG_DEFINEDNESS_AT_STARTUP 1
1169b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
11705db15403e889d4db339b342bc2a824ef0bfaa654sewardj#  elif defined(VGP_mips32_linux)
1171737548c7409e5d46b72a914ae1dc6d1a48199d25florian   vg_assert(0 == sizeof(VexGuestMIPS32State) % LibVEX_GUEST_STATE_ALIGN);
11725db15403e889d4db339b342bc2a824ef0bfaa654sewardj   /* Zero out the initial state, and set up the simulated FPU in a
11735db15403e889d4db339b342bc2a824ef0bfaa654sewardj      sane way. */
11745db15403e889d4db339b342bc2a824ef0bfaa654sewardj   LibVEX_GuestMIPS32_initialise(&arch->vex);
11755db15403e889d4db339b342bc2a824ef0bfaa654sewardj
11765db15403e889d4db339b342bc2a824ef0bfaa654sewardj   /* Zero out the shadow areas. */
11775db15403e889d4db339b342bc2a824ef0bfaa654sewardj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestMIPS32State));
11785db15403e889d4db339b342bc2a824ef0bfaa654sewardj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestMIPS32State));
11795db15403e889d4db339b342bc2a824ef0bfaa654sewardj
11805db15403e889d4db339b342bc2a824ef0bfaa654sewardj   arch->vex.guest_r29 = iifii.initial_client_SP;
11815db15403e889d4db339b342bc2a824ef0bfaa654sewardj   arch->vex.guest_PC = iifii.initial_client_IP;
11825db15403e889d4db339b342bc2a824ef0bfaa654sewardj   arch->vex.guest_r31 = iifii.initial_client_SP;
11835db15403e889d4db339b342bc2a824ef0bfaa654sewardj
1184a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   if (iifii.arch_elf_state.overall_fp_mode == VKI_FP_FR1) {
1185a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      arch->vex.guest_CP0_status |= MIPS_CP0_STATUS_FR;
1186a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   }
1187a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
11884df0bfc0614379192c780c944415dc420d9cfe8epetarj#   elif defined(VGP_mips64_linux)
1189737548c7409e5d46b72a914ae1dc6d1a48199d25florian   vg_assert(0 == sizeof(VexGuestMIPS64State) % LibVEX_GUEST_STATE_ALIGN);
11904df0bfc0614379192c780c944415dc420d9cfe8epetarj   /* Zero out the initial state, and set up the simulated FPU in a
11914df0bfc0614379192c780c944415dc420d9cfe8epetarj      sane way. */
11924df0bfc0614379192c780c944415dc420d9cfe8epetarj   LibVEX_GuestMIPS64_initialise(&arch->vex);
11934df0bfc0614379192c780c944415dc420d9cfe8epetarj
11944df0bfc0614379192c780c944415dc420d9cfe8epetarj   /* Zero out the shadow areas. */
11954df0bfc0614379192c780c944415dc420d9cfe8epetarj   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestMIPS64State));
11964df0bfc0614379192c780c944415dc420d9cfe8epetarj   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestMIPS64State));
11974df0bfc0614379192c780c944415dc420d9cfe8epetarj
11984df0bfc0614379192c780c944415dc420d9cfe8epetarj   arch->vex.guest_r29 = iifii.initial_client_SP;
11994df0bfc0614379192c780c944415dc420d9cfe8epetarj   arch->vex.guest_PC = iifii.initial_client_IP;
12004df0bfc0614379192c780c944415dc420d9cfe8epetarj   arch->vex.guest_r31 = iifii.initial_client_SP;
12014df0bfc0614379192c780c944415dc420d9cfe8epetarj
120217c110443e39c0c63bb298689cad31e0b4671dfesewardj#  else
120317c110443e39c0c63bb298689cad31e0b4671dfesewardj#    error Unknown platform
120417c110443e39c0c63bb298689cad31e0b4671dfesewardj#  endif
120517c110443e39c0c63bb298689cad31e0b4671dfesewardj
120681de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian#  if !defined(PRECISE_GUEST_REG_DEFINEDNESS_AT_STARTUP)
120717c110443e39c0c63bb298689cad31e0b4671dfesewardj   /* Tell the tool that we just wrote to the registers. */
120817c110443e39c0c63bb298689cad31e0b4671dfesewardj   VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
120917c110443e39c0c63bb298689cad31e0b4671dfesewardj             sizeof(VexGuestArchState));
121081de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian#  endif
121181de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian
121281de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian   /* Tell the tool about the client data segment and then kill it which will
121381de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian      make it inaccessible/unaddressable. */
121481de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian   const NSegment *seg = VG_(am_find_nsegment)(VG_(brk_base));
121581de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian   vg_assert(seg);
121681de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian   vg_assert(seg->kind == SkAnonC);
121781de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian   VG_TRACK(new_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base),
121881de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian            1/*tid*/);
121981de065f33b4fbcb02a9a5b7fd75fdb6bde1506fflorian   VG_TRACK(die_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base));
122017c110443e39c0c63bb298689cad31e0b4671dfesewardj}
122117c110443e39c0c63bb298689cad31e0b4671dfesewardj
12228b68b64759254d514d98328c496cbd88cde4c9a5njn#endif // defined(VGO_linux)
122317c110443e39c0c63bb298689cad31e0b4671dfesewardj
122417c110443e39c0c63bb298689cad31e0b4671dfesewardj/*--------------------------------------------------------------------*/
12258b68b64759254d514d98328c496cbd88cde4c9a5njn/*---                                                              ---*/
122617c110443e39c0c63bb298689cad31e0b4671dfesewardj/*--------------------------------------------------------------------*/
1227