1
2/*--------------------------------------------------------------------*/
3/*--- Startup: create initial process image on Solaris             ---*/
4/*---                                            initimg-solaris.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2011-2017 Petr Pavlu
12      setup@dagobah.cz
13
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27   02111-1307, USA.
28
29   The GNU General Public License is contained in the file COPYING.
30*/
31
32/* Copyright 2013-2017, Ivo Raisr <ivosh@ivosh.net>. */
33
34#if defined(VGO_solaris)
35
36/* Note: This file is based on initimg-linux.c. */
37
38#include "pub_core_basics.h"
39#include "pub_core_vki.h"
40#include "pub_core_debuglog.h"
41#include "pub_core_libcbase.h"
42#include "pub_core_libcassert.h"
43#include "pub_core_libcfile.h"
44#include "pub_core_libcproc.h"
45#include "pub_core_libcprint.h"
46#include "pub_core_xarray.h"
47#include "pub_core_clientstate.h"
48#include "pub_core_aspacemgr.h"
49#include "pub_core_mallocfree.h"
50#include "pub_core_machine.h"
51#include "pub_core_ume.h"
52#include "pub_core_options.h"
53#include "pub_core_syswrap.h"
54#include "pub_core_tooliface.h"       /* VG_TRACK */
55#include "pub_core_threadstate.h"     /* ThreadArchState */
56#include "priv_initimg_pathscan.h"
57#include "pub_core_initimg.h"         /* self */
58
59
60/*====================================================================*/
61/*=== Loading the client                                           ===*/
62/*====================================================================*/
63
64/* Load the client whose name is VG_(argv_the_exename). */
65static void load_client(/*OUT*/ExeInfo *info,
66                        /*OUT*/HChar *out_exe_name, SizeT out_exe_name_size)
67{
68   const HChar *exe_name;
69   Int ret;
70   SysRes res;
71
72   vg_assert(VG_(args_the_exename));
73   exe_name = ML_(find_executable)(VG_(args_the_exename));
74
75   if (!exe_name) {
76      VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
77      /* Return POSIX's NOTFOUND. */
78      VG_(exit)(127);
79      /*NOTREACHED*/
80   }
81
82   VG_(memset)(info, 0, sizeof(*info));
83   ret = VG_(do_exec)(exe_name, info);
84   if (ret < 0) {
85      VG_(printf)("valgrind: could not execute '%s'\n", exe_name);
86      VG_(exit)(1);
87      /*NOTREACHED*/
88   }
89
90   /* The client was successfully loaded!  Continue. */
91
92   /* Save resolved exename. */
93   if (VG_(strlen)(exe_name) + 1 > out_exe_name_size) {
94      /* This should not really happen. */
95      VG_(printf)("valgrind: execname %s is too long\n", exe_name);
96      VG_(exit)(1);
97      /*NOTREACHED*/
98   }
99   VG_(strcpy)(out_exe_name, exe_name);
100
101   /* Get hold of a file descriptor which refers to the client executable.
102      This is needed for attaching to GDB. */
103   res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
104   if (!sr_isError(res))
105      VG_(cl_exec_fd) = sr_Res(res);
106
107   /* Set initial brk values. */
108   if (info->ldsoexec) {
109      VG_(brk_base) = VG_(brk_limit) = -1;
110   } else {
111      VG_(brk_base) = VG_(brk_limit) = info->brkbase;
112   }
113}
114
115
116/*====================================================================*/
117/*=== Setting up the client's environment                          ===*/
118/*====================================================================*/
119
120/* Prepare the client's environment.  This is basically a copy of our
121   environment, except:
122
123     LD_PRELOAD=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
124                ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
125                $LD_PRELOAD
126
127   If this is missing, then it is added.
128
129   Also, remove any binding for VALGRIND_LAUNCHER=.  The client should not be
130   able to see this.
131
132   If this needs to handle any more variables it should be hacked into
133   something table driven.  The copy is VG_(malloc)'d space.
134*/
135static HChar **setup_client_env(HChar **origenv, const HChar *toolname)
136{
137   const HChar *ld_preload = "LD_PRELOAD=";
138   SizeT ld_preload_len = VG_(strlen)(ld_preload);
139   Bool ld_preload_done = False;
140   SizeT vglib_len = VG_(strlen)(VG_(libdir));
141
142   HChar **cpp;
143   HChar **ret;
144   HChar *preload_tool_path;
145   SizeT envc, i;
146
147   /* Alloc space for the
148        <path>/vgpreload_core-<platform>.so and
149        <path>/vgpreload_<tool>-<platform>.so
150      paths.  We might not need the space for the tool path, but it doesn't
151      hurt to over-allocate briefly.  */
152   SizeT preload_core_path_size = vglib_len + sizeof("/vgpreload_core-") - 1
153                                            + sizeof(VG_PLATFORM) - 1
154                                            + sizeof(".so");
155   SizeT preload_tool_path_size = vglib_len + sizeof("/vgpreload_") - 1
156                                            + VG_(strlen)(toolname) + 1 /*-*/
157                                            + sizeof(VG_PLATFORM) - 1
158                                            + sizeof(".so");
159   SizeT preload_string_size = preload_core_path_size
160                               + preload_tool_path_size;
161   HChar *preload_string = VG_(malloc)("initimg-solaris.sce.1",
162                                       preload_string_size);
163
164   /* Check that the parameters are sane. */
165   vg_assert(origenv);
166   vg_assert(toolname);
167
168   /* Determine if there's a vgpreload_<tool>-<platform>.so file, and setup
169      preload_string. */
170   preload_tool_path = VG_(malloc)("initimg-solaris.sce.2",
171                                   preload_tool_path_size);
172   VG_(sprintf)(preload_tool_path, "%s/vgpreload_%s-%s.so", VG_(libdir),
173                toolname, VG_PLATFORM);
174   if (!VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/)) {
175      /* The tool's .so exists, put it into LD_PRELOAD with the core's so. */
176      VG_(sprintf)(preload_string, "%s/vgpreload_core-%s.so:%s", VG_(libdir),
177                   VG_PLATFORM, preload_tool_path);
178   }
179   else {
180      /* The tool's .so doesn't exist, put only the core's .so into
181         LD_PRELOAD. */
182      VG_(sprintf)(preload_string, "%s/vgpreload_core-%s.so", VG_(libdir),
183                   VG_PLATFORM);
184   }
185   VG_(free)(preload_tool_path);
186
187   VG_(debugLog)(2, "initimg", "preload_string:\n");
188   VG_(debugLog)(2, "initimg", "  \"%s\"\n", preload_string);
189
190   /* Count the original size of the env. */
191   envc = 0;
192   for (cpp = origenv; *cpp; cpp++)
193      envc++;
194
195   /* Allocate a new space, envc + 1 new entry + NULL. */
196   ret = VG_(malloc)("initimg-solaris.sce.3", sizeof(HChar*) * (envc + 1 + 1));
197
198   /* Copy it over. */
199   for (cpp = ret; *origenv; )
200      *cpp++ = *origenv++;
201   *cpp = NULL;
202
203   vg_assert(envc == cpp - ret);
204
205   /* Walk over the new environment, mashing as we go. */
206   for (cpp = ret; *cpp; cpp++) {
207      if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len))
208         continue;
209
210      /* LD_PRELOAD entry found, smash it. */
211      SizeT size = VG_(strlen)(*cpp) + 1 /*:*/
212                                     + preload_string_size;
213      HChar *cp = VG_(malloc)("initimg-solaris.sce.4", size);
214
215      VG_(sprintf)(cp, "%s%s:%s", ld_preload, preload_string,
216                   (*cpp) + ld_preload_len);
217      *cpp = cp;
218
219      ld_preload_done = True;
220   }
221
222   /* Add the missing bits. */
223   if (!ld_preload_done) {
224      SizeT size = ld_preload_len + preload_string_size;
225      HChar *cp = VG_(malloc)("initimg-solaris.sce.5", size);
226
227      VG_(sprintf)(cp, "%s%s", ld_preload, preload_string);
228      ret[envc++] = cp;
229   }
230
231   /* We've got ret[0 .. envc-1] live now. */
232
233   /* Find and remove a binding for VALGRIND_LAUNCHER. */
234   {
235      const HChar *v_launcher = VALGRIND_LAUNCHER "=";
236      SizeT v_launcher_len = VG_(strlen)(v_launcher);
237
238      for (i = 0; i < envc; i++)
239         if (!VG_(memcmp)(ret[i], v_launcher, v_launcher_len)) {
240            /* VALGRIND_LAUNCHER was found. */
241            break;
242         }
243
244      if (i < envc) {
245         /* VALGRIND_LAUNCHER was found, remove it. */
246         for (; i < envc - 1; i++)
247            ret[i] = ret[i + 1];
248         envc--;
249      }
250   }
251
252   VG_(free)(preload_string);
253   ret[envc] = NULL;
254
255   return ret;
256}
257
258
259/*====================================================================*/
260/*=== Setting up the client's stack                                ===*/
261/*====================================================================*/
262
263/* Add a string onto the string table, and return its address. */
264static HChar *copy_str(HChar **tab, const HChar *str)
265{
266   HChar *cp = *tab;
267   HChar *orig = cp;
268
269   while (*str)
270      *cp++ = *str++;
271   *cp++ = '\0';
272
273   *tab = cp;
274
275   return orig;
276}
277
278#if defined(SOLARIS_RESERVE_SYSSTAT_ADDR) || \
279    defined(SOLARIS_RESERVE_SYSSTAT_ZONE_ADDR)
280#define ORIG_AUXV_PRESENT 1
281#endif
282
283#if defined(ORIG_AUXV_PRESENT)
284/* The auxiliary vector might not be present. So we cross-check pointers from
285   argv and envp pointing to the string table. */
286static vki_auxv_t *find_original_auxv(Addr init_sp)
287{
288   HChar **sp = (HChar **) init_sp;
289   HChar *lowest_str_ptr = (HChar *) UINTPTR_MAX; // lowest ptr to string table
290
291   sp++; // skip argc
292
293   while (*sp != NULL) { // skip argv
294      if (*sp < lowest_str_ptr)
295         lowest_str_ptr = *sp;
296      sp++;
297   }
298   sp++;
299
300   while (*sp != 0) { // skip env
301      if (*sp < lowest_str_ptr)
302         lowest_str_ptr = *sp;
303      sp++;
304   }
305   sp++;
306
307   if ((Addr) sp < (Addr) lowest_str_ptr) {
308      return (vki_auxv_t *) sp;
309   } else {
310      return NULL;
311   }
312}
313
314static void copy_auxv_entry(const vki_auxv_t *orig_auxv, Int type,
315                            const HChar *type_name, vki_auxv_t *auxv)
316{
317   vg_assert(auxv != NULL);
318
319   if (orig_auxv == NULL) {
320      VG_(printf)("valgrind: Cannot locate auxiliary vector.\n");
321      VG_(printf)("valgrind: Cannot continue. Sorry.\n\n");
322      VG_(exit)(1);
323   }
324
325   for ( ; orig_auxv->a_type != VKI_AT_NULL; orig_auxv++) {
326      if (orig_auxv->a_type == type) {
327         auxv->a_type = type;
328         auxv->a_un.a_val = orig_auxv->a_un.a_val;
329         return;
330      }
331   }
332
333   VG_(printf)("valgrind: Cannot locate %s in the aux\n", type_name);
334   VG_(printf)("valgrind: vector. Cannot continue. Sorry.\n\n");
335   VG_(exit)(1);
336}
337#endif /* ORIG_AUXV_PRESENT */
338
339/* This sets up the client's initial stack, containing the args,
340   environment and aux vector.
341
342   The format of the stack is:
343
344   higher address +-----------------+ <- clstack_end
345                  |                 |
346                  : string table    :
347                  |                 |
348                  +-----------------+
349                  | AT_NULL         |
350                  -                 -
351                  | auxv            |
352                  +-----------------+
353                  | NULL            |
354                  -                 -
355                  | envp            |
356                  +-----------------+
357                  | NULL            |
358                  -                 -
359                  | argv            |
360                  +-----------------+
361                  | argc            |
362   lower address  +-----------------+ <- sp
363                  | undefined       |
364                  :                 :
365
366   Allocate and create the initial client stack.  It is allocated down from
367   clstack_end, which was previously determined by the address space manager.
368   The returned value is the SP value for the client.
369
370   Note that auxiliary vector is *not* created by kernel on illumos and
371   Solaris 11 if the program is statically linked (which is our case).
372   Although we now taught Solaris 12 to create the auxiliary vector, we still
373   have to build auxv from scratch, to make the code consistent. */
374
375static Addr setup_client_stack(Addr init_sp,
376                               HChar **orig_envp,
377                               const ExeInfo *info,
378                               Addr clstack_end,
379                               SizeT clstack_max_size,
380                               const HChar *resolved_exe_name)
381{
382   SysRes res;
383   HChar **cpp;
384   HChar *strtab;       /* string table */
385   HChar *stringbase;
386   Addr *ptr;
387   vki_auxv_t *auxv;
388   SizeT stringsize;    /* total size of strings in bytes */
389   SizeT auxsize;       /* total size of auxv in bytes */
390   Int argc;            /* total argc */
391   Int envc;            /* total number of env vars */
392   SizeT stacksize;     /* total client stack size */
393   Addr client_SP;      /* client stack base (initial SP) */
394   Addr clstack_start;
395   Int i;
396
397   vg_assert(VG_IS_PAGE_ALIGNED(clstack_end + 1));
398   vg_assert(VG_(args_the_exename));
399   vg_assert(VG_(args_for_client));
400
401#  if defined(ORIG_AUXV_PRESENT)
402   /* Get the original auxv (if any). */
403   vki_auxv_t *orig_auxv = find_original_auxv(init_sp);
404#  endif /* ORIG_AUXV_PRESENT */
405
406   /* ==================== compute sizes ==================== */
407
408   /* First of all, work out how big the client stack will be. */
409   stringsize = 0;
410
411   /* Paste on the extra args if the loader needs them (i.e. the #!
412      interpreter and its argument). */
413   argc = 0;
414   if (info->interp_name) {
415      argc++;
416      stringsize += VG_(strlen)(info->interp_name) + 1;
417   }
418   if (info->interp_args) {
419      argc++;
420      stringsize += VG_(strlen)(info->interp_args) + 1;
421   }
422
423   /* Now scan the args we're given... */
424   argc++;
425   stringsize += VG_(strlen)(VG_(args_the_exename)) + 1;
426   for (i = 0; i < VG_(sizeXA)(VG_(args_for_client)); i++) {
427      argc++;
428      stringsize += VG_(strlen)(*(HChar**)
429                                  VG_(indexXA)(VG_(args_for_client), i)) + 1;
430   }
431
432   /* ...and the environment. */
433   envc = 0;
434   for (cpp = orig_envp; *cpp; cpp++) {
435      envc++;
436      stringsize += VG_(strlen)(*cpp) + 1;
437   }
438
439   /* Now, how big is the auxv?
440
441      AT_SUN_PLATFORM
442      AT_SUN_EXECNAME
443      AT_PHDR            (not for elfs with no PT_PHDR, such as ld.so.1)
444      AT_BASE
445      AT_ENTRY
446      AT_FLAGS
447      AT_PAGESZ
448      AT_SUN_AUXFLAFGS
449      AT_SUN_HWCAP
450      AT_SUN_SYSSTAT_ADDR      (if supported)
451      AT_SUN_SYSSTAT_ZONE_ADDR (if supported)
452      AT_NULL
453
454      It would be possible to also add AT_PHENT, AT_PHNUM, AT_SUN_LDDATA,
455      but they don't seem to be so important. */
456   auxsize = 10 * sizeof(*auxv);
457#  if defined(SOLARIS_RESERVE_SYSSTAT_ADDR)
458   auxsize += sizeof(*auxv);
459#  endif
460#  if defined(SOLARIS_RESERVE_SYSSTAT_ZONE_ADDR)
461   auxsize += sizeof(*auxv);
462#  endif
463
464#  if defined(VGA_x86) || defined(VGA_amd64)
465   /* AT_SUN_PLATFORM string. */
466   stringsize += VG_(strlen)("i86pc") + 1;
467#  else
468#    error "Unknown architecture"
469#  endif
470   /* AT_SUN_EXECNAME string. */
471   stringsize += VG_(strlen)(resolved_exe_name) + 1;
472
473   /* Calculate how big the client stack is. */
474   stacksize =
475      sizeof(Word) +                            /* argc */
476      sizeof(HChar**) +                         /* argc[0] == exename */
477      sizeof(HChar**) * argc +                  /* argv */
478      sizeof(HChar**) +                         /* terminal NULL */
479      sizeof(HChar**) * envc +                  /* envp */
480      sizeof(HChar**) +                         /* terminal NULL */
481      auxsize +                                 /* auxv */
482      VG_ROUNDUP(stringsize, sizeof(Word));     /* strings (aligned) */
483
484   /* The variable client_SP is the client's stack pointer. */
485   client_SP = clstack_end - stacksize;
486   client_SP = VG_ROUNDDN(client_SP, 16); /* Make stack 16 byte aligned. */
487
488   /* Calculate base of the string table (aligned). */
489   stringbase = (HChar*)clstack_end - VG_ROUNDUP(stringsize, sizeof(Int));
490   strtab = stringbase;
491
492   clstack_start = VG_PGROUNDDN(client_SP);
493
494   /* Calculate the max stack size. */
495   clstack_max_size = VG_PGROUNDUP(clstack_max_size);
496
497   /* Record stack extent -- needed for stack-change code. */
498   VG_(clstk_start_base) = clstack_start;
499   VG_(clstk_end) = clstack_end;
500   VG_(clstk_max_size) = clstack_max_size;
501
502   if (0)
503      VG_(printf)("stringsize=%lu, auxsize=%lu, stacksize=%lu, maxsize=%#lx\n"
504                  "clstack_start %#lx\n"
505                  "clstack_end   %#lx\n",
506                  stringsize, auxsize, stacksize, clstack_max_size,
507                  clstack_start, clstack_end);
508
509   /* ==================== allocate space ==================== */
510
511   {
512      SizeT anon_size = clstack_end - clstack_start + 1;
513      SizeT resvn_size = clstack_max_size - anon_size;
514      Addr anon_start = clstack_start;
515      Addr resvn_start = anon_start - resvn_size;
516      SizeT inner_HACK = 0;
517      Bool ok;
518
519      /* So far we've only accounted for space requirements down to the stack
520         pointer.  If this target's ABI requires a redzone below the stack
521         pointer, we need to allocate an extra page, to handle the worst case
522         in which the stack pointer is almost at the bottom of a page, and so
523         there is insufficient room left over to put the redzone in.  In this
524         case the simple thing to do is allocate an extra page, by shrinking
525         the reservation by one page and growing the anonymous area by a
526         corresponding page. */
527      vg_assert(VG_STACK_REDZONE_SZB >= 0);
528      vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE);
529      if (VG_STACK_REDZONE_SZB > 0) {
530         vg_assert(resvn_size > VKI_PAGE_SIZE);
531         resvn_size -= VKI_PAGE_SIZE;
532         anon_start -= VKI_PAGE_SIZE;
533         anon_size += VKI_PAGE_SIZE;
534      }
535
536      vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
537      vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
538      vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
539      vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
540      vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
541
542#     ifdef ENABLE_INNER
543      /* Create 1M non-fault-extending stack. */
544      inner_HACK = 1024 * 1024;
545#     endif
546
547      if (0)
548         VG_(printf)("resvn_start=%#lx, resvn_size=%#lx\n"
549                     "anon_start=%#lx, anon_size=%#lx\n",
550                     resvn_start, resvn_size, anon_start, anon_size);
551
552      /* Create a shrinkable reservation followed by an anonymous segment.
553         Together these constitute a growdown stack. */
554      ok = VG_(am_create_reservation)(resvn_start,
555                                      resvn_size - inner_HACK,
556                                      SmUpper,
557                                      anon_size + inner_HACK);
558      if (ok) {
559         /* Allocate a stack - mmap enough space for the stack. */
560         res = VG_(am_mmap_anon_fixed_client)(anon_start - inner_HACK,
561                                              anon_size + inner_HACK,
562                                              info->stack_prot);
563      }
564      if (!ok || sr_isError(res)) {
565         /* Allocation of the stack failed.  We have to stop. */
566         VG_(printf)("valgrind: "
567                     "I failed to allocate space for the application's stack.\n");
568         VG_(printf)("valgrind: "
569                     "This may be the result of a very large --main-stacksize=\n");
570         VG_(printf)("valgrind: setting.  Cannot continue.  Sorry.\n\n");
571         VG_(exit)(1);
572         /*NOTREACHED*/
573      }
574   }
575
576   /* ==================== create client stack ==================== */
577
578   ptr = (Addr*)client_SP;
579
580   /* Copy-out client argc. */
581   *ptr++ = argc;
582
583   /* Copy-out client argv. */
584   if (info->interp_name)
585      *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
586   if (info->interp_args)
587      *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
588
589   *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
590   for (i = 0; i < VG_(sizeXA)(VG_(args_for_client)); i++)
591      *ptr++ = (Addr)copy_str(
592                  &strtab, *(HChar**) VG_(indexXA)(VG_(args_for_client), i));
593   *ptr++ = 0;
594
595   /* Copy-out envp. */
596   VG_(client_envp) = (HChar**)ptr;
597   for (cpp = orig_envp; *cpp; ptr++, cpp++)
598      *ptr = (Addr)copy_str(&strtab, *cpp);
599   *ptr++ = 0;
600
601   /* Create aux vector. */
602   auxv = (auxv_t*)ptr;
603   VG_(client_auxv) = (UWord*)ptr;
604
605   /* AT_SUN_PLATFORM */
606   auxv->a_type = VKI_AT_SUN_PLATFORM;
607#  if defined(VGA_x86) || defined(VGA_amd64)
608   auxv->a_un.a_ptr = copy_str(&strtab, "i86pc");
609#  else
610#    error "Unknown architecture"
611#  endif
612   auxv++;
613
614   /* AT_SUN_EXECNAME */
615   auxv->a_type = VKI_AT_SUN_EXECNAME;
616   auxv->a_un.a_ptr = copy_str(&strtab, resolved_exe_name);
617   auxv++;
618
619   /* AT_PHDR */
620   if ((info->real_phdr_present) && (info->phdr != 0)) {
621      auxv->a_type = VKI_AT_PHDR;
622      auxv->a_un.a_val = info->phdr;
623      auxv++;
624   }
625
626   /* AT_BASE */
627   auxv->a_type = VKI_AT_BASE;
628   auxv->a_un.a_val = info->interp_offset;
629   auxv++;
630
631   /* AT_ENTRY */
632   auxv->a_type = VKI_AT_ENTRY;
633   auxv->a_un.a_val = info->entry;
634   auxv++;
635
636   /* AT_FLAGS */
637   auxv->a_type = VKI_AT_FLAGS;
638#  if defined(VGA_x86) || defined(VGA_amd64)
639   auxv->a_un.a_val = 0; /* 0 on i86pc */
640#  else
641#    error "Unknown architecture"
642#  endif
643   auxv++;
644
645   /* AT_PAGESZ */
646   auxv->a_type = VKI_AT_PAGESZ;
647   auxv->a_un.a_val = VKI_PAGE_SIZE;
648   auxv++;
649
650   /* AT_SUN_AUXFLAFGS */
651   auxv->a_type = VKI_AT_SUN_AUXFLAGS;
652   /* XXX Handle AF_SUN_SETUGID? */
653   auxv->a_un.a_val = VKI_AF_SUN_HWCAPVERIFY;
654   auxv++;
655
656   /* AT_SUN_HWCAP */
657   {
658      VexArch vex_arch;
659      VexArchInfo vex_archinfo;
660      UInt hwcaps;
661
662      VG_(machine_get_VexArchInfo)(&vex_arch, &vex_archinfo);
663
664#     if defined(VGA_x86)
665      vg_assert(vex_arch == VexArchX86);
666
667      /* Set default hwcaps. */
668      hwcaps =
669           VKI_AV_386_FPU       /* x87-style floating point */
670         | VKI_AV_386_TSC       /* rdtsc insn */
671         | VKI_AV_386_CX8       /* cmpxchg8b insn */
672         | VKI_AV_386_SEP       /* sysenter and sysexit */
673         | VKI_AV_386_AMD_SYSC  /* AMD's syscall and sysret */
674         | VKI_AV_386_CMOV      /* conditional move insns */
675         | VKI_AV_386_MMX       /* MMX insn */
676         | VKI_AV_386_AHF;      /* lahf/sahf insns */
677
678      /* Handle additional hwcaps. */
679      if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE1)
680         hwcaps |=
681              VKI_AV_386_FXSR   /* fxsave and fxrstor */
682            | VKI_AV_386_SSE;   /* SSE insns and regs  */
683      if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE2) {
684         vg_assert(vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE1);
685         hwcaps |=
686              VKI_AV_386_SSE2;  /* SSE2 insns and regs */
687      }
688      if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE3) {
689         vg_assert(vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE2);
690         hwcaps |=
691              VKI_AV_386_SSE3   /* SSE3 insns and regs */
692            | VKI_AV_386_SSSE3; /* Intel SSSE3 insns */
693      }
694      if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_LZCNT)
695         hwcaps |=
696              VKI_AV_386_AMD_LZCNT; /* AMD's LZCNT insn */
697
698      /* No support for:
699         AV_386_AMD_MMX         AMD's MMX insns
700         AV_386_AMD_3DNow       AMD's 3Dnow! insns
701         AV_386_AMD_3DNowx      AMD's 3Dnow! extended insns
702         AV_386_CX16            cmpxchg16b insn
703         AV_386_TSCP            rdtscp instruction
704         AV_386_AMD_SSE4A       AMD's SSE4A insns
705         AV_386_POPCNT          POPCNT insn
706         AV_386_SSE4_1          Intel SSE4.1 insns
707         AV_386_SSE4_2          Intel SSE4.2 insns
708         AV_386_MOVBE           Intel MOVBE insns
709         AV_386_AES             Intel AES insns
710         AV_386_PCLMULQDQ       Intel PCLMULQDQ insn
711         AV_386_XSAVE           Intel XSAVE/XRSTOR insns
712         AV_386_AVX             Intel AVX insns
713         illumos only:
714            AV_386_VMX          Intel VMX support
715            AV_386_AMD_SVM      AMD SVM support
716         solaris only:
717            AV_386_AMD_XOP      AMD XOP insns
718            AV_386_AMD_FMA4     AMD FMA4 insns */
719
720#     elif defined(VGA_amd64)
721      vg_assert(vex_arch == VexArchAMD64);
722
723      /* Set default hwcaps. */
724      hwcaps =
725           VKI_AV_386_FPU       /* x87-style floating point */
726         | VKI_AV_386_TSC       /* rdtsc insn */
727         | VKI_AV_386_CX8       /* cmpxchg8b insn */
728         | VKI_AV_386_AMD_SYSC  /* AMD's syscall and sysret */
729         | VKI_AV_386_CMOV      /* conditional move insns */
730         | VKI_AV_386_MMX       /* MMX insn */
731         | VKI_AV_386_AHF       /* lahf/sahf insns */
732         | VKI_AV_386_FXSR      /* fxsave and fxrstor */
733         | VKI_AV_386_SSE       /* SSE insns and regs  */
734         | VKI_AV_386_SSE2;     /* SSE2 insns and regs */
735
736      /* Handle additional hwcaps. */
737      if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3)
738         hwcaps |=
739              VKI_AV_386_SSE3   /* SSE3 insns and regs */
740            | VKI_AV_386_SSSE3; /* Intel SSSE3 insns */
741      if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16)
742         hwcaps |=
743              VKI_AV_386_CX16;  /* cmpxchg16b insn */
744      if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_LZCNT)
745         hwcaps |=
746              VKI_AV_386_AMD_LZCNT; /* AMD's LZCNT insn */
747      if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_RDTSCP)
748         hwcaps |=
749              VKI_AV_386_TSCP;  /* rdtscp instruction */
750      if ((vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3) &&
751          (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16)) {
752         /* The CPUID simulation provided by VEX claims to have POPCNT, AES
753            and SSE4 (SSE4.1/SSE4.2) in the SSE3+CX16 configuration. */
754         hwcaps |=
755              VKI_AV_386_POPCNT /* POPCNT insn */
756            | VKI_AV_386_AES    /* Intel AES insns */
757            | VKI_AV_386_SSE4_1 /* Intel SSE4.1 insns */
758            | VKI_AV_386_SSE4_2; /* Intel SSE4.2 insns */
759      }
760      if ((vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3) &&
761          (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16) &&
762          (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_AVX)) {
763         /* The CPUID simulation provided by VEX claims to have PCLMULQDQ and
764            XSAVE in the SSE3+CX16+AVX configuration. */
765         hwcaps |=
766              VKI_AV_386_PCLMULQDQ /* Intel PCLMULQDQ insn */
767            | VKI_AV_386_XSAVE; /* Intel XSAVE/XRSTOR insns */
768      }
769      /* No support for:
770         AV_386_SEP             sysenter and sysexit
771         AV_386_AMD_MMX         AMD's MMX insns
772         AV_386_AMD_3DNow       AMD's 3Dnow! insns
773         AV_386_AMD_3DNowx      AMD's 3Dnow! extended insns
774         AV_386_AMD_SSE4A       AMD's SSE4A insns
775         AV_386_MOVBE           Intel MOVBE insns
776         AV_386_AVX             Intel AVX insns
777         illumos only:
778            AV_386_VMX          Intel VMX support
779            AV_386_AMD_SVM      AMD SVM support
780         solaris only:
781            AV_386_AMD_XOP      AMD XOP insns
782            AV_386_AMD_FMA4     AMD FMA4 insns
783
784         TODO VEX supports AVX, BMI and AVX2. Investigate if they can be
785         enabled on Solaris/illumos.
786       */
787
788#     else
789#       error "Unknown architecture"
790#     endif
791
792      auxv->a_type = VKI_AT_SUN_HWCAP;
793      auxv->a_un.a_val = hwcaps;
794      auxv++;
795   }
796
797   /* AT_SUN_HWCAP2 */
798   {
799      /* No support for:
800         illumos only:
801            AV_386_2_F16C       F16C half percision extensions
802            AV_386_2_RDRAND     RDRAND insn
803         solaris only:
804            AV2_386_RDRAND      Intel RDRAND insns
805            AV2_386_FMA         Intel FMA insn
806            AV2_386_F16C        IEEE half precn(float) insn
807            AV2_386_AMD_TBM     AMD TBM insn
808            AV2_386_BMI1        Intel BMI1 insn
809            AV2_386_FSGSBASE    Intel RD/WR FS/GSBASE insn
810            AV2_386_AVX2        Intel AVX2 insns
811            AV2_386_BMI2        Intel BMI2 insns
812            AV2_386_HLE         Intel HLE insns
813            AV2_386_RTM         Intel RTM insns
814            AV2_386_EFS         Intel Enhanced Fast String
815            AV2_386_RDSEED      Intel RDSEED insn
816            AV2_386_ADX         Intel ADX insns
817            AV2_386_PRFCHW      Intel PREFETCHW hint
818       */
819   }
820
821#  if defined(SOLARIS_RESERVE_SYSSTAT_ADDR)
822   /* AT_SUN_SYSSTAT_ADDR */
823   copy_auxv_entry(orig_auxv, VKI_AT_SUN_SYSSTAT_ADDR,
824                   "AT_SUN_SYSSTAT_ADDR", auxv);
825   VG_(change_mapping_ownership)(auxv->a_un.a_val, True);
826   auxv++;
827#  endif
828
829#  if defined(SOLARIS_RESERVE_SYSSTAT_ZONE_ADDR)
830   /* AT_SUN_SYSSTAT_ZONE_ADDR */
831   copy_auxv_entry(orig_auxv, VKI_AT_SUN_SYSSTAT_ZONE_ADDR,
832                   "AT_SUN_SYSSTAT_ZONE_ADDR", auxv);
833   VG_(change_mapping_ownership)(auxv->a_un.a_val, True);
834   auxv++;
835#  endif
836
837   /* AT_NULL */
838   auxv->a_type = VKI_AT_NULL;
839   auxv->a_un.a_val = 0;
840
841   vg_assert(strtab - stringbase == stringsize);
842
843   /* The variable client_SP is now pointing at client's argc/argv. */
844
845   if (0)
846      VG_(printf)("startup SP = %#lx\n", client_SP);
847   return client_SP;
848}
849
850/*====================================================================*/
851/*=== TOP-LEVEL: VG_(setup_client_initial_image)                   ===*/
852/*====================================================================*/
853
854/* Create the client's initial memory image. */
855IIFinaliseImageInfo VG_(ii_create_image)(IICreateImageInfo iicii,
856                                         const VexArchInfo *vex_archinfo)
857{
858   ExeInfo info;
859   HChar **env = NULL;
860   HChar resolved_exe_name[VKI_PATH_MAX];
861
862   IIFinaliseImageInfo iifii;
863   VG_(memset)(&iifii, 0, sizeof(iifii));
864
865   //--------------------------------------------------------------
866   // Load client executable, finding in $PATH if necessary
867   //   p: early_process_cmd_line_options()  [for 'exec', 'need_help']
868   //   p: layout_remaining_space            [so there's space]
869   //--------------------------------------------------------------
870   VG_(debugLog)(1, "initimg", "Loading client\n");
871
872   if (!VG_(args_the_exename)) {
873      VG_(err_missing_prog)();
874      /*NOTREACHED*/
875   }
876
877   load_client(&info, resolved_exe_name, sizeof(resolved_exe_name));
878   iifii.initial_client_IP = info.init_ip;
879   /* Note: TOC isn't available on Solaris. */
880   iifii.initial_client_TOC = info.init_toc;
881   iifii.initial_client_TP = info.init_thrptr;
882   /* Note that iifii.client_auxv is never set on Solaris, because it isn't
883      necessary to have this value in VG_(ii_finalise_image). */
884
885   //--------------------------------------------------------------
886   // Set up client's environment
887   //   p: set-libdir                       [for VG_(libdir)]
888   //   p: early_process_cmd_line_options() [for toolname]
889   //--------------------------------------------------------------
890   VG_(debugLog)(1, "initimg", "Setup client env\n");
891   env = setup_client_env(iicii.envp, iicii.toolname);
892
893   //--------------------------------------------------------------
894   // Setup client stack and EIP
895   //   p: load_client()     [for 'info']
896   //   p: fix_environment() [for 'env']
897   //--------------------------------------------------------------
898   {
899      /* When allocating space for the client stack, take notice of the
900         --main-stacksize value.  This makes it possible to run programs with
901         very large (primary) stack requirements simply by specifying
902         --main-stacksize. */
903      /* Logic is as follows:
904         - By default, use the client's current stack rlimit.
905         - If that exceeds 16M, clamp to 16M.
906         - If a larger --main-stacksize value is specified, use that instead.
907         - In all situations, the minimum allowed stack size is 1M.
908      */
909      Addr init_sp = (Addr) (iicii.argv - 1);
910      SizeT m1  = 1024 * 1024;
911      SizeT m16 = 16 * m1;
912      SizeT szB = (SizeT)VG_(client_rlimit_stack).rlim_cur;
913      if (szB < m1)
914         szB = m1;
915      if (szB > m16)
916         szB = m16;
917
918      if (VG_(clo_main_stacksize) > 0)
919         szB = VG_(clo_main_stacksize);
920      if (szB < m1)
921         szB = m1;
922
923      szB = VG_PGROUNDUP(szB);
924      VG_(debugLog)(1, "initimg",
925                       "Setup client stack: size will be %ld\n", szB);
926
927      iifii.clstack_max_size = szB;
928      iifii.initial_client_SP = setup_client_stack(init_sp, env, &info,
929                                                   iicii.clstack_end,
930                                                   iifii.clstack_max_size,
931                                                   resolved_exe_name);
932      VG_(free)(env);
933
934      VG_(debugLog)(2, "initimg", "Client info: "
935                       "initial_IP=%#lx, initial_TOC=%#lx, brk_base=%#lx\n",
936                       iifii.initial_client_IP, iifii.initial_client_TOC,
937                       VG_(brk_base));
938      VG_(debugLog)(2, "initimg", "Client info: "
939                       "initial_SP=%#lx, max_stack_size=%lu\n",
940                       iifii.initial_client_SP,
941                       iifii.clstack_max_size);
942   }
943
944   if (info.ldsoexec) {
945      /* We are executing the runtime linker itself.
946         Initial data (brk) segment is setup on demand, after the target dynamic
947         executable has been loaded or when a first brk() syscall is made.
948         It cannot be established now because it would conflict with a temporary
949         stack which ld.so.1 (when executed directly) uses for loading the
950         target dynamic executable. See PRE(sys_brk) in syswrap-solaris.c. */
951   } else {
952      if (!VG_(setup_client_dataseg)()) {
953         VG_(printf)("valgrind: cannot initialize data segment (brk).\n");
954         VG_(exit)(1);
955      }
956   }
957
958   VG_(free)(info.interp_name);
959   VG_(free)(info.interp_args);
960   return iifii;
961}
962
963
964/*====================================================================*/
965/*=== TOP-LEVEL: VG_(finalise_image)                               ===*/
966/*====================================================================*/
967
968/* Just before starting the client, we may need to make final adjustments to
969   its initial image.  Also we need to set up the VEX guest state for thread 1
970   (the root thread) and copy in essential starting values.  This is handed
971   the IIFinaliseImageInfo created by VG_(ii_create_image).
972*/
973void VG_(ii_finalise_image)(IIFinaliseImageInfo iifii)
974{
975   ThreadArchState *arch = &VG_(threads)[1].arch;
976
977#  if defined(VGA_x86)
978   vg_assert(0 == sizeof(VexGuestX86State) % LibVEX_GUEST_STATE_ALIGN);
979
980   /* Zero out the initial state, and set up the simulated FPU in a sane
981      way. */
982   LibVEX_GuestX86_initialise(&arch->vex);
983
984   /* Zero out the shadow areas. */
985   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State));
986   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State));
987
988   /* Put essential stuff into the new state. */
989   arch->vex.guest_ESP = iifii.initial_client_SP;
990   arch->vex.guest_EIP = iifii.initial_client_IP;
991   LibVEX_GuestX86_put_eflags(VKI_PSL_USER, &arch->vex);
992
993   /* Set %cs, %ds, %ss and %es to default values. */
994   __asm__ __volatile__ ("movw %%cs, %[cs]" : [cs] "=m" (arch->vex.guest_CS));
995   __asm__ __volatile__ ("movw %%ds, %[ds]" : [ds] "=m" (arch->vex.guest_DS));
996   __asm__ __volatile__ ("movw %%ss, %[ss]" : [ss] "=m" (arch->vex.guest_SS));
997   __asm__ __volatile__ ("movw %%es, %[es]" : [es] "=m" (arch->vex.guest_ES));
998
999   {
1000      /* Initial thread pointer value will be saved in GDT when the thread is
1001         started in the syswrap module and a thread's GDT is allocated. */
1002      ThreadOSstate *os = &VG_(threads)[1].os_state;
1003      os->thrptr = iifii.initial_client_TP;
1004   }
1005
1006#  elif defined(VGA_amd64)
1007   vg_assert(0 == sizeof(VexGuestAMD64State) % LibVEX_GUEST_STATE_ALIGN);
1008
1009   /* Zero out the initial state, and set up the simulated FPU in a sane
1010      way. */
1011   LibVEX_GuestAMD64_initialise(&arch->vex);
1012
1013   /* Zero out the shadow areas. */
1014   VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State));
1015   VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State));
1016
1017   /* Put essential stuff into the new state. */
1018   arch->vex.guest_RSP = iifii.initial_client_SP;
1019   arch->vex.guest_RIP = iifii.initial_client_IP;
1020   arch->vex.guest_FS_CONST = iifii.initial_client_TP;
1021   LibVEX_GuestAMD64_put_rflags(VKI_PSL_USER, &arch->vex);
1022
1023#  else
1024#    error "Unknown platform"
1025#  endif
1026
1027   /* Tell the tool that we just wrote to the registers. */
1028   VG_TRACK(post_reg_write, Vg_CoreStartup, 1/*tid*/, 0/*offset*/,
1029            sizeof(VexGuestArchState));
1030
1031   if (VG_(brk_base) != -1 ) {
1032      /* Make inaccessible/unaddressable the end of the client data segment.
1033         See PRE(sys_brk) in syswrap-solaris.c for details. */
1034      VG_(track_client_dataseg)(1 /* tid */);
1035   }
1036}
1037
1038#endif // defined(VGO_solaris)
1039
1040/*--------------------------------------------------------------------*/
1041/*---                                                              ---*/
1042/*--------------------------------------------------------------------*/
1043