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-2015 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-2015, 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). */
load_client(ExeInfo * info,HChar * out_exe_name,SizeT out_exe_name_size)65 static 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 */
setup_client_env(HChar ** origenv,const HChar * toolname)135 static 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. */
copy_str(HChar ** tab,const HChar * str)264 static 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. */
find_original_auxv(Addr init_sp)286 static 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 
copy_auxv_entry(const vki_auxv_t * orig_auxv,Int type,const HChar * type_name,vki_auxv_t * auxv)314 static 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 
setup_client_stack(Addr init_sp,HChar ** orig_envp,const ExeInfo * info,Addr clstack_end,SizeT clstack_max_size,const HChar * resolved_exe_name)375 static 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_FLAGS
446       AT_PAGESZ
447       AT_SUN_AUXFLAFGS
448       AT_SUN_HWCAP
449       AT_SUN_SYSSTAT_ADDR      (if supported)
450       AT_SUN_SYSSTAT_ZONE_ADDR (if supported)
451       AT_NULL
452 
453       It would be possible to also add AT_PHENT, AT_PHNUM, AT_ENTRY,
454       AT_SUN_LDDATA, but they don't seem to be so important. */
455    auxsize = 9 * sizeof(*auxv);
456 #  if defined(SOLARIS_RESERVE_SYSSTAT_ADDR)
457    auxsize += sizeof(*auxv);
458 #  endif
459 #  if defined(SOLARIS_RESERVE_SYSSTAT_ZONE_ADDR)
460    auxsize += sizeof(*auxv);
461 #  endif
462 
463 #  if defined(VGA_x86) || defined(VGA_amd64)
464    /* AT_SUN_PLATFORM string. */
465    stringsize += VG_(strlen)("i86pc") + 1;
466 #  else
467 #    error "Unknown architecture"
468 #  endif
469    /* AT_SUN_EXECNAME string. */
470    stringsize += VG_(strlen)(resolved_exe_name) + 1;
471 
472    /* Calculate how big the client stack is. */
473    stacksize =
474       sizeof(Word) +                            /* argc */
475       sizeof(HChar**) +                         /* argc[0] == exename */
476       sizeof(HChar**) * argc +                  /* argv */
477       sizeof(HChar**) +                         /* terminal NULL */
478       sizeof(HChar**) * envc +                  /* envp */
479       sizeof(HChar**) +                         /* terminal NULL */
480       auxsize +                                 /* auxv */
481       VG_ROUNDUP(stringsize, sizeof(Word));     /* strings (aligned) */
482 
483    /* The variable client_SP is the client's stack pointer. */
484    client_SP = clstack_end - stacksize;
485    client_SP = VG_ROUNDDN(client_SP, 16); /* Make stack 16 byte aligned. */
486 
487    /* Calculate base of the string table (aligned). */
488    stringbase = (HChar*)clstack_end - VG_ROUNDUP(stringsize, sizeof(Int));
489    strtab = stringbase;
490 
491    clstack_start = VG_PGROUNDDN(client_SP);
492 
493    /* Calculate the max stack size. */
494    clstack_max_size = VG_PGROUNDUP(clstack_max_size);
495 
496    /* Record stack extent -- needed for stack-change code. */
497    VG_(clstk_start_base) = clstack_start;
498    VG_(clstk_end) = clstack_end;
499    VG_(clstk_max_size) = clstack_max_size;
500 
501    if (0)
502       VG_(printf)("stringsize=%lu, auxsize=%lu, stacksize=%lu, maxsize=%#lx\n"
503                   "clstack_start %#lx\n"
504                   "clstack_end   %#lx\n",
505                   stringsize, auxsize, stacksize, clstack_max_size,
506                   clstack_start, clstack_end);
507 
508    /* ==================== allocate space ==================== */
509 
510    {
511       SizeT anon_size = clstack_end - clstack_start + 1;
512       SizeT resvn_size = clstack_max_size - anon_size;
513       Addr anon_start = clstack_start;
514       Addr resvn_start = anon_start - resvn_size;
515       SizeT inner_HACK = 0;
516       Bool ok;
517 
518       /* So far we've only accounted for space requirements down to the stack
519          pointer.  If this target's ABI requires a redzone below the stack
520          pointer, we need to allocate an extra page, to handle the worst case
521          in which the stack pointer is almost at the bottom of a page, and so
522          there is insufficient room left over to put the redzone in.  In this
523          case the simple thing to do is allocate an extra page, by shrinking
524          the reservation by one page and growing the anonymous area by a
525          corresponding page. */
526       vg_assert(VG_STACK_REDZONE_SZB >= 0);
527       vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE);
528       if (VG_STACK_REDZONE_SZB > 0) {
529          vg_assert(resvn_size > VKI_PAGE_SIZE);
530          resvn_size -= VKI_PAGE_SIZE;
531          anon_start -= VKI_PAGE_SIZE;
532          anon_size += VKI_PAGE_SIZE;
533       }
534 
535       vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
536       vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
537       vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
538       vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
539       vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
540 
541 #     ifdef ENABLE_INNER
542       /* Create 1M non-fault-extending stack. */
543       inner_HACK = 1024 * 1024;
544 #     endif
545 
546       if (0)
547          VG_(printf)("resvn_start=%#lx, resvn_size=%#lx\n"
548                      "anon_start=%#lx, anon_size=%#lx\n",
549                      resvn_start, resvn_size, anon_start, anon_size);
550 
551       /* Create a shrinkable reservation followed by an anonymous segment.
552          Together these constitute a growdown stack. */
553       ok = VG_(am_create_reservation)(resvn_start,
554                                       resvn_size - inner_HACK,
555                                       SmUpper,
556                                       anon_size + inner_HACK);
557       if (ok) {
558          /* Allocate a stack - mmap enough space for the stack. */
559          res = VG_(am_mmap_anon_fixed_client)(anon_start - inner_HACK,
560                                               anon_size + inner_HACK,
561                                               info->stack_prot);
562       }
563       if (!ok || sr_isError(res)) {
564          /* Allocation of the stack failed.  We have to stop. */
565          VG_(printf)("valgrind: "
566                      "I failed to allocate space for the application's stack.\n");
567          VG_(printf)("valgrind: "
568                      "This may be the result of a very large --main-stacksize=\n");
569          VG_(printf)("valgrind: setting.  Cannot continue.  Sorry.\n\n");
570          VG_(exit)(1);
571          /*NOTREACHED*/
572       }
573    }
574 
575    /* ==================== create client stack ==================== */
576 
577    ptr = (Addr*)client_SP;
578 
579    /* Copy-out client argc. */
580    *ptr++ = argc;
581 
582    /* Copy-out client argv. */
583    if (info->interp_name) {
584       *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
585       VG_(free)(info->interp_name);
586    }
587    if (info->interp_args) {
588       *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
589       VG_(free)(info->interp_args);
590    }
591 
592    *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
593    for (i = 0; i < VG_(sizeXA)(VG_(args_for_client)); i++)
594       *ptr++ = (Addr)copy_str(
595                   &strtab, *(HChar**) VG_(indexXA)(VG_(args_for_client), i));
596    *ptr++ = 0;
597 
598    /* Copy-out envp. */
599    VG_(client_envp) = (HChar**)ptr;
600    for (cpp = orig_envp; *cpp; ptr++, cpp++)
601       *ptr = (Addr)copy_str(&strtab, *cpp);
602    *ptr++ = 0;
603 
604    /* Create aux vector. */
605    auxv = (auxv_t*)ptr;
606    VG_(client_auxv) = (UWord*)ptr;
607 
608    /* AT_SUN_PLATFORM */
609    auxv->a_type = VKI_AT_SUN_PLATFORM;
610 #  if defined(VGA_x86) || defined(VGA_amd64)
611    auxv->a_un.a_ptr = copy_str(&strtab, "i86pc");
612 #  else
613 #    error "Unknown architecture"
614 #  endif
615    auxv++;
616 
617    /* AT_SUN_EXECNAME */
618    auxv->a_type = VKI_AT_SUN_EXECNAME;
619    auxv->a_un.a_ptr = copy_str(&strtab, resolved_exe_name);
620    auxv++;
621 
622    /* AT_PHDR */
623    if ((info->real_phdr_present) && (info->phdr != 0)) {
624       auxv->a_type = VKI_AT_PHDR;
625       auxv->a_un.a_val = info->phdr;
626       auxv++;
627    }
628 
629    /* AT_BASE */
630    auxv->a_type = VKI_AT_BASE;
631    auxv->a_un.a_val = info->interp_offset;
632    auxv++;
633 
634    /* AT_FLAGS */
635    auxv->a_type = VKI_AT_FLAGS;
636 #  if defined(VGA_x86) || defined(VGA_amd64)
637    auxv->a_un.a_val = 0; /* 0 on i86pc */
638 #  else
639 #    error "Unknown architecture"
640 #  endif
641    auxv++;
642 
643    /* AT_PAGESZ */
644    auxv->a_type = VKI_AT_PAGESZ;
645    auxv->a_un.a_val = VKI_PAGE_SIZE;
646    auxv++;
647 
648    /* AT_SUN_AUXFLAFGS */
649    auxv->a_type = VKI_AT_SUN_AUXFLAGS;
650    /* XXX Handle AF_SUN_SETUGID? */
651    auxv->a_un.a_val = VKI_AF_SUN_HWCAPVERIFY;
652    auxv++;
653 
654    /* AT_SUN_HWCAP */
655    {
656       VexArch vex_arch;
657       VexArchInfo vex_archinfo;
658       UInt hwcaps;
659 
660       VG_(machine_get_VexArchInfo)(&vex_arch, &vex_archinfo);
661 
662 #     if defined(VGA_x86)
663       vg_assert(vex_arch == VexArchX86);
664 
665       /* Set default hwcaps. */
666       hwcaps =
667            VKI_AV_386_FPU       /* x87-style floating point */
668          | VKI_AV_386_TSC       /* rdtsc insn */
669          | VKI_AV_386_CX8       /* cmpxchg8b insn */
670          | VKI_AV_386_SEP       /* sysenter and sysexit */
671          | VKI_AV_386_AMD_SYSC  /* AMD's syscall and sysret */
672          | VKI_AV_386_CMOV      /* conditional move insns */
673          | VKI_AV_386_MMX       /* MMX insn */
674          | VKI_AV_386_AHF;      /* lahf/sahf insns */
675 
676       /* Handle additional hwcaps. */
677       if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE1)
678          hwcaps |=
679               VKI_AV_386_FXSR   /* fxsave and fxrstor */
680             | VKI_AV_386_SSE;   /* SSE insns and regs  */
681       if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE2) {
682          vg_assert(vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE1);
683          hwcaps |=
684               VKI_AV_386_SSE2;  /* SSE2 insns and regs */
685       }
686       if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE3) {
687          vg_assert(vex_archinfo.hwcaps & VEX_HWCAPS_X86_SSE2);
688          hwcaps |=
689               VKI_AV_386_SSE3   /* SSE3 insns and regs */
690             | VKI_AV_386_SSSE3; /* Intel SSSE3 insns */
691       }
692       if (vex_archinfo.hwcaps & VEX_HWCAPS_X86_LZCNT)
693          hwcaps |=
694               VKI_AV_386_AMD_LZCNT; /* AMD's LZCNT insn */
695 
696       /* No support for:
697          AV_386_AMD_MMX         AMD's MMX insns
698          AV_386_AMD_3DNow       AMD's 3Dnow! insns
699          AV_386_AMD_3DNowx      AMD's 3Dnow! extended insns
700          AV_386_CX16            cmpxchg16b insn
701          AV_386_TSCP            rdtscp instruction
702          AV_386_AMD_SSE4A       AMD's SSE4A insns
703          AV_386_POPCNT          POPCNT insn
704          AV_386_SSE4_1          Intel SSE4.1 insns
705          AV_386_SSE4_2          Intel SSE4.2 insns
706          AV_386_MOVBE           Intel MOVBE insns
707          AV_386_AES             Intel AES insns
708          AV_386_PCLMULQDQ       Intel PCLMULQDQ insn
709          AV_386_XSAVE           Intel XSAVE/XRSTOR insns
710          AV_386_AVX             Intel AVX insns
711          illumos only:
712             AV_386_VMX          Intel VMX support
713             AV_386_AMD_SVM      AMD SVM support
714          solaris only:
715             AV_386_AMD_XOP      AMD XOP insns
716             AV_386_AMD_FMA4     AMD FMA4 insns */
717 
718 #     elif defined(VGA_amd64)
719       vg_assert(vex_arch == VexArchAMD64);
720 
721       /* Set default hwcaps. */
722       hwcaps =
723            VKI_AV_386_FPU       /* x87-style floating point */
724          | VKI_AV_386_TSC       /* rdtsc insn */
725          | VKI_AV_386_CX8       /* cmpxchg8b insn */
726          | VKI_AV_386_AMD_SYSC  /* AMD's syscall and sysret */
727          | VKI_AV_386_CMOV      /* conditional move insns */
728          | VKI_AV_386_MMX       /* MMX insn */
729          | VKI_AV_386_AHF       /* lahf/sahf insns */
730          | VKI_AV_386_FXSR      /* fxsave and fxrstor */
731          | VKI_AV_386_SSE       /* SSE insns and regs  */
732          | VKI_AV_386_SSE2;     /* SSE2 insns and regs */
733 
734       /* Handle additional hwcaps. */
735       if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3)
736          hwcaps |=
737               VKI_AV_386_SSE3   /* SSE3 insns and regs */
738             | VKI_AV_386_SSSE3; /* Intel SSSE3 insns */
739       if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16)
740          hwcaps |=
741               VKI_AV_386_CX16;  /* cmpxchg16b insn */
742       if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_LZCNT)
743          hwcaps |=
744               VKI_AV_386_AMD_LZCNT; /* AMD's LZCNT insn */
745       if (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_RDTSCP)
746          hwcaps |=
747               VKI_AV_386_TSCP;  /* rdtscp instruction */
748       if ((vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3) &&
749           (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16)) {
750          /* The CPUID simulation provided by VEX claims to have POPCNT, AES
751             and SSE4 (SSE4.1/SSE4.2) in the SSE3+CX16 configuration. */
752          hwcaps |=
753               VKI_AV_386_POPCNT /* POPCNT insn */
754             | VKI_AV_386_AES    /* Intel AES insns */
755             | VKI_AV_386_SSE4_1 /* Intel SSE4.1 insns */
756             | VKI_AV_386_SSE4_2; /* Intel SSE4.2 insns */
757       }
758       if ((vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_SSE3) &&
759           (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_CX16) &&
760           (vex_archinfo.hwcaps & VEX_HWCAPS_AMD64_AVX)) {
761          /* The CPUID simulation provided by VEX claims to have PCLMULQDQ and
762             XSAVE in the SSE3+CX16+AVX configuration. */
763          hwcaps |=
764               VKI_AV_386_PCLMULQDQ /* Intel PCLMULQDQ insn */
765             | VKI_AV_386_XSAVE; /* Intel XSAVE/XRSTOR insns */
766       }
767       /* No support for:
768          AV_386_SEP             sysenter and sysexit
769          AV_386_AMD_MMX         AMD's MMX insns
770          AV_386_AMD_3DNow       AMD's 3Dnow! insns
771          AV_386_AMD_3DNowx      AMD's 3Dnow! extended insns
772          AV_386_AMD_SSE4A       AMD's SSE4A insns
773          AV_386_MOVBE           Intel MOVBE insns
774          AV_386_AVX             Intel AVX insns
775          illumos only:
776             AV_386_VMX          Intel VMX support
777             AV_386_AMD_SVM      AMD SVM support
778          solaris only:
779             AV_386_AMD_XOP      AMD XOP insns
780             AV_386_AMD_FMA4     AMD FMA4 insns
781 
782          TODO VEX supports AVX, BMI and AVX2. Investigate if they can be
783          enabled on Solaris/illumos.
784        */
785 
786 #     else
787 #       error "Unknown architecture"
788 #     endif
789 
790       auxv->a_type = VKI_AT_SUN_HWCAP;
791       auxv->a_un.a_val = hwcaps;
792       auxv++;
793    }
794 
795    /* AT_SUN_HWCAP2 */
796    {
797       /* No support for:
798          illumos only:
799             AV_386_2_F16C       F16C half percision extensions
800             AV_386_2_RDRAND     RDRAND insn
801          solaris only:
802             AV2_386_RDRAND      Intel RDRAND insns
803             AV2_386_FMA         Intel FMA insn
804             AV2_386_F16C        IEEE half precn(float) insn
805             AV2_386_AMD_TBM     AMD TBM insn
806             AV2_386_BMI1        Intel BMI1 insn
807             AV2_386_FSGSBASE    Intel RD/WR FS/GSBASE insn
808             AV2_386_AVX2        Intel AVX2 insns
809             AV2_386_BMI2        Intel BMI2 insns
810             AV2_386_HLE         Intel HLE insns
811             AV2_386_RTM         Intel RTM insns
812             AV2_386_EFS         Intel Enhanced Fast String
813             AV2_386_RDSEED      Intel RDSEED insn
814             AV2_386_ADX         Intel ADX insns
815             AV2_386_PRFCHW      Intel PREFETCHW hint
816        */
817    }
818 
819 #  if defined(SOLARIS_RESERVE_SYSSTAT_ADDR)
820    /* AT_SUN_SYSSTAT_ADDR */
821    copy_auxv_entry(orig_auxv, VKI_AT_SUN_SYSSTAT_ADDR,
822                    "AT_SUN_SYSSTAT_ADDR", auxv);
823    VG_(change_mapping_ownership)(auxv->a_un.a_val, True);
824    auxv++;
825 #  endif
826 
827 #  if defined(SOLARIS_RESERVE_SYSSTAT_ZONE_ADDR)
828    /* AT_SUN_SYSSTAT_ZONE_ADDR */
829    copy_auxv_entry(orig_auxv, VKI_AT_SUN_SYSSTAT_ZONE_ADDR,
830                    "AT_SUN_SYSSTAT_ZONE_ADDR", auxv);
831    VG_(change_mapping_ownership)(auxv->a_un.a_val, True);
832    auxv++;
833 #  endif
834 
835    /* AT_NULL */
836    auxv->a_type = VKI_AT_NULL;
837    auxv->a_un.a_val = 0;
838 
839    vg_assert(strtab - stringbase == stringsize);
840 
841    /* The variable client_SP is now pointing at client's argc/argv. */
842 
843    if (0)
844       VG_(printf)("startup SP = %#lx\n", client_SP);
845    return client_SP;
846 }
847 
848 /*====================================================================*/
849 /*=== TOP-LEVEL: VG_(setup_client_initial_image)                   ===*/
850 /*====================================================================*/
851 
852 /* Create the client's initial memory image. */
VG_(ii_create_image)853 IIFinaliseImageInfo VG_(ii_create_image)(IICreateImageInfo iicii,
854                                          const VexArchInfo *vex_archinfo)
855 {
856    ExeInfo info;
857    HChar **env = NULL;
858    HChar resolved_exe_name[VKI_PATH_MAX];
859 
860    IIFinaliseImageInfo iifii;
861    VG_(memset)(&iifii, 0, sizeof(iifii));
862 
863    //--------------------------------------------------------------
864    // Load client executable, finding in $PATH if necessary
865    //   p: early_process_cmd_line_options()  [for 'exec', 'need_help']
866    //   p: layout_remaining_space            [so there's space]
867    //--------------------------------------------------------------
868    VG_(debugLog)(1, "initimg", "Loading client\n");
869 
870    if (!VG_(args_the_exename)) {
871       VG_(err_missing_prog)();
872       /*NOTREACHED*/
873    }
874 
875    load_client(&info, resolved_exe_name, sizeof(resolved_exe_name));
876    iifii.initial_client_IP = info.init_ip;
877    /* Note: TOC isn't available on Solaris. */
878    iifii.initial_client_TOC = info.init_toc;
879    iifii.initial_client_TP = info.init_thrptr;
880    /* Note that iifii.client_auxv is never set on Solaris, because it isn't
881       necessary to have this value in VG_(ii_finalise_image). */
882 
883    //--------------------------------------------------------------
884    // Set up client's environment
885    //   p: set-libdir                       [for VG_(libdir)]
886    //   p: early_process_cmd_line_options() [for toolname]
887    //--------------------------------------------------------------
888    VG_(debugLog)(1, "initimg", "Setup client env\n");
889    env = setup_client_env(iicii.envp, iicii.toolname);
890 
891    //--------------------------------------------------------------
892    // Setup client stack and EIP
893    //   p: load_client()     [for 'info']
894    //   p: fix_environment() [for 'env']
895    //--------------------------------------------------------------
896    {
897       /* When allocating space for the client stack, take notice of the
898          --main-stacksize value.  This makes it possible to run programs with
899          very large (primary) stack requirements simply by specifying
900          --main-stacksize. */
901       /* Logic is as follows:
902          - By default, use the client's current stack rlimit.
903          - If that exceeds 16M, clamp to 16M.
904          - If a larger --main-stacksize value is specified, use that instead.
905          - In all situations, the minimum allowed stack size is 1M.
906       */
907       Addr init_sp = (Addr) (iicii.argv - 1);
908       SizeT m1  = 1024 * 1024;
909       SizeT m16 = 16 * m1;
910       SizeT szB = (SizeT)VG_(client_rlimit_stack).rlim_cur;
911       if (szB < m1)
912          szB = m1;
913       if (szB > m16)
914          szB = m16;
915 
916       if (VG_(clo_main_stacksize) > 0)
917          szB = VG_(clo_main_stacksize);
918       if (szB < m1)
919          szB = m1;
920 
921       szB = VG_PGROUNDUP(szB);
922       VG_(debugLog)(1, "initimg",
923                        "Setup client stack: size will be %ld\n", szB);
924 
925       iifii.clstack_max_size = szB;
926       iifii.initial_client_SP = setup_client_stack(init_sp, env, &info,
927                                                    iicii.clstack_end,
928                                                    iifii.clstack_max_size,
929                                                    resolved_exe_name);
930       VG_(free)(env);
931 
932       VG_(debugLog)(2, "initimg", "Client info: "
933                        "initial_IP=%#lx, initial_TOC=%#lx, brk_base=%#lx\n",
934                        iifii.initial_client_IP, iifii.initial_client_TOC,
935                        VG_(brk_base));
936       VG_(debugLog)(2, "initimg", "Client info: "
937                        "initial_SP=%#lx, max_stack_size=%lu\n",
938                        iifii.initial_client_SP,
939                        iifii.clstack_max_size);
940    }
941 
942    if (info.ldsoexec) {
943       /* We are executing the runtime linker itself.
944          Initial data (brk) segment is setup on demand, after the target dynamic
945          executable has been loaded or when a first brk() syscall is made.
946          It cannot be established now because it would conflict with a temporary
947          stack which ld.so.1 (when executed directly) uses for loading the
948          target dynamic executable. See PRE(sys_brk) in syswrap-solaris.c. */
949    } else {
950       if (!VG_(setup_client_dataseg)()) {
951          VG_(printf)("valgrind: cannot initialize data segment (brk).\n");
952          VG_(exit)(1);
953       }
954    }
955 
956    return iifii;
957 }
958 
959 
960 /*====================================================================*/
961 /*=== TOP-LEVEL: VG_(finalise_image)                               ===*/
962 /*====================================================================*/
963 
964 /* Just before starting the client, we may need to make final adjustments to
965    its initial image.  Also we need to set up the VEX guest state for thread 1
966    (the root thread) and copy in essential starting values.  This is handed
967    the IIFinaliseImageInfo created by VG_(ii_create_image).
968 */
VG_(ii_finalise_image)969 void VG_(ii_finalise_image)(IIFinaliseImageInfo iifii)
970 {
971    ThreadArchState *arch = &VG_(threads)[1].arch;
972 
973 #  if defined(VGA_x86)
974    vg_assert(0 == sizeof(VexGuestX86State) % LibVEX_GUEST_STATE_ALIGN);
975 
976    /* Zero out the initial state, and set up the simulated FPU in a sane
977       way. */
978    LibVEX_GuestX86_initialise(&arch->vex);
979 
980    /* Zero out the shadow areas. */
981    VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State));
982    VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State));
983 
984    /* Put essential stuff into the new state. */
985    arch->vex.guest_ESP = iifii.initial_client_SP;
986    arch->vex.guest_EIP = iifii.initial_client_IP;
987    LibVEX_GuestX86_put_eflags(VKI_PSL_USER, &arch->vex);
988 
989    /* Set %cs, %ds, %ss and %es to default values. */
990    __asm__ __volatile__ ("movw %%cs, %[cs]" : [cs] "=m" (arch->vex.guest_CS));
991    __asm__ __volatile__ ("movw %%ds, %[ds]" : [ds] "=m" (arch->vex.guest_DS));
992    __asm__ __volatile__ ("movw %%ss, %[ss]" : [ss] "=m" (arch->vex.guest_SS));
993    __asm__ __volatile__ ("movw %%es, %[es]" : [es] "=m" (arch->vex.guest_ES));
994 
995    {
996       /* Initial thread pointer value will be saved in GDT when the thread is
997          started in the syswrap module and a thread's GDT is allocated. */
998       ThreadOSstate *os = &VG_(threads)[1].os_state;
999       os->thrptr = iifii.initial_client_TP;
1000    }
1001 
1002 #  elif defined(VGA_amd64)
1003    vg_assert(0 == sizeof(VexGuestAMD64State) % LibVEX_GUEST_STATE_ALIGN);
1004 
1005    /* Zero out the initial state, and set up the simulated FPU in a sane
1006       way. */
1007    LibVEX_GuestAMD64_initialise(&arch->vex);
1008 
1009    /* Zero out the shadow areas. */
1010    VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State));
1011    VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State));
1012 
1013    /* Put essential stuff into the new state. */
1014    arch->vex.guest_RSP = iifii.initial_client_SP;
1015    arch->vex.guest_RIP = iifii.initial_client_IP;
1016    arch->vex.guest_FS_CONST = iifii.initial_client_TP;
1017    LibVEX_GuestAMD64_put_rflags(VKI_PSL_USER, &arch->vex);
1018 
1019 #  else
1020 #    error "Unknown platform"
1021 #  endif
1022 
1023    /* Tell the tool that we just wrote to the registers. */
1024    VG_TRACK(post_reg_write, Vg_CoreStartup, 1/*tid*/, 0/*offset*/,
1025             sizeof(VexGuestArchState));
1026 
1027    if (VG_(brk_base) != -1 ) {
1028       /* Make inaccessible/unaddressable the end of the client data segment.
1029          See PRE(sys_brk) in syswrap-solaris.c for details. */
1030       VG_(track_client_dataseg)(1 /* tid */);
1031    }
1032 }
1033 
1034 #endif // defined(VGO_solaris)
1035 
1036 /*--------------------------------------------------------------------*/
1037 /*---                                                              ---*/
1038 /*--------------------------------------------------------------------*/
1039