Bug 439685 compiler warning in callgrind/main.c
[valgrind.git] / coregrind / m_initimg / initimg-freebsd.c
blobba01279ebb56b559a0b7c683e9c8d2e7c588ef8c
2 /*--------------------------------------------------------------------*/
3 /*--- Startup: create initial process image on FreeBSD ---*/
4 /*--- initimg-freebsd.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2009 Julian Seward
12 jseward@acm.org
13 Copyright (C) 2018-2021 Paul Floyd
14 pjfloyd@wanadoo.fr
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation; either version 2 of the
19 License, or (at your option) any later version.
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, see <http://www.gnu.org/licenses/>.
29 The GNU General Public License is contained in the file COPYING.
32 #if defined(VGO_freebsd)
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_debuglog.h"
37 #include "pub_core_libcbase.h"
38 #include "pub_core_libcassert.h"
39 #include "pub_core_libcfile.h"
40 #include "pub_core_libcproc.h"
41 #include "pub_core_libcprint.h"
42 #include "pub_core_xarray.h"
43 #include "pub_core_clientstate.h"
44 #include "pub_core_aspacemgr.h"
45 #include "pub_core_mallocfree.h"
46 #include "pub_core_machine.h"
47 #include "pub_core_ume.h"
48 #include "pub_core_options.h"
49 #include "pub_core_syscall.h"
50 #include "pub_core_tooliface.h" /* VG_TRACK */
51 #include "pub_core_threadstate.h" /* ThreadArchState */
52 #include "pub_core_pathscan.h"
53 #include "pub_core_initimg.h" /* self */
55 /*====================================================================*/
56 /*=== Loading the client ===*/
57 /*====================================================================*/
59 /* Load the client whose name is VG_(argv_the_exename). */
61 static void load_client ( /*OUT*/ExeInfo* info,
62 /*OUT*/Addr* client_ip,
63 /*OUT*/Addr* client_toc)
65 const HChar* exe_name;
66 Int ret;
67 SysRes res;
69 vg_assert( VG_(args_the_exename) != NULL);
70 exe_name = VG_(find_executable)( VG_(args_the_exename) );
72 if (!exe_name) {
73 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
74 VG_(exit)(127); // 127 is Posix NOTFOUND
77 VG_(memset)(info, 0, sizeof(*info));
78 ret = VG_(do_exec)(exe_name, info);
79 if (ret < 0) {
80 VG_(printf)("valgrind: could not execute '%s'\n", exe_name);
81 VG_(exit)(1);
84 // The client was successfully loaded! Continue.
86 /* Get hold of a file descriptor which refers to the client
87 executable. This is needed for attaching to GDB. */
88 res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
89 if (!sr_isError(res)) {
90 VG_(cl_exec_fd) = sr_Res(res);
93 /* Copy necessary bits of 'info' that were filled in */
94 *client_ip = info->init_ip;
95 *client_toc = info->init_toc;
96 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
100 /*====================================================================*/
101 /*=== Setting up the client's environment ===*/
102 /*====================================================================*/
104 /* Prepare the client's environment. This is basically a copy of our
105 environment, except:
107 LD_PRELOAD=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
108 ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
109 $LD_PRELOAD
111 If this is missing, then it is added.
113 Also, remove any binding for VALGRIND_LAUNCHER=. The client should
114 not be able to see this.
116 If this needs to handle any more variables it should be hacked
117 into something table driven. The copy is VG_(malloc)'d space.
119 static HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
121 vg_assert(origenv);
122 vg_assert(toolname);
124 const HChar* preload_core = "vgpreload_core";
125 const HChar* ld_preload = "LD_PRELOAD=";
126 const HChar* v_launcher = VALGRIND_LAUNCHER "=";
127 Int ld_preload_len = VG_(strlen)( ld_preload );
128 Int v_launcher_len = VG_(strlen)( v_launcher );
129 Bool ld_preload_done = False;
130 #if defined(VGP_x86_freebsd)
131 const HChar* ld_32_preload = "LD_32_PRELOAD=";
132 Int ld_32_preload_len = VG_(strlen)( ld_32_preload );
133 Bool ld_32_preload_done = False;
134 #endif
135 Int vglib_len = VG_(strlen)(VG_(libdir));
136 Bool debug = False;
138 HChar** cpp;
139 HChar** ret;
140 HChar* preload_tool_path;
141 Int envc;
142 Int i;
144 /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
145 paths. We might not need the space for vgpreload_<tool>.so, but it
146 doesn't hurt to over-allocate briefly. The 16s are just cautious
147 slop. */
148 Int preload_core_path_len = vglib_len + sizeof(preload_core)
149 + sizeof(VG_PLATFORM) + 16;
150 Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname)
151 + sizeof(VG_PLATFORM) + 16;
152 Int preload_string_len = preload_core_path_len + preload_tool_path_len;
153 HChar* preload_string = VG_(malloc)("initimg-freebsd.sce.1",
154 preload_string_len);
155 /* Determine if there's a vgpreload_<tool>_<platform>.so file, and setup
156 preload_string. */
157 preload_tool_path = VG_(malloc)("initimg-freebsd.sce.2", preload_tool_path_len);
158 VG_(snprintf)(preload_tool_path, preload_tool_path_len,
159 "%s/vgpreload_%s-%s.so", VG_(libdir), toolname, VG_PLATFORM);
160 if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
161 VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so:%s",
162 VG_(libdir), preload_core, VG_PLATFORM, preload_tool_path);
163 } else {
164 VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so",
165 VG_(libdir), preload_core, VG_PLATFORM);
167 VG_(free)(preload_tool_path);
169 VG_(debugLog)(2, "initimg", "preload_string:\n");
170 VG_(debugLog)(2, "initimg", " \"%s\"\n", preload_string);
172 /* Count the original size of the env */
173 if (debug) {
174 VG_(printf)("\n\n");
176 envc = 0;
177 for (cpp = origenv; cpp && *cpp; cpp++) {
178 envc++;
179 if (debug) {
180 VG_(printf)("XXXXXXXXX: BEFORE %s\n", *cpp);
184 /* Allocate a new space */
185 ret = VG_(malloc) ("initimg-freebsd.sce.3",
186 sizeof(HChar *) * (envc+2+1)); /* 2 new entries + NULL */
188 /* copy it over */
189 for (cpp = ret; *origenv; ) {
190 if (debug) {
191 VG_(printf)("XXXXXXXXX: COPY %s\n", *origenv);
193 *cpp++ = *origenv++;
195 *cpp = NULL;
196 *(cpp + 1) = NULL;
198 vg_assert(envc == (cpp - ret));
200 /* Walk over the new environment, mashing as we go */
201 for (cpp = ret; cpp && *cpp; cpp++) {
202 if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) {
203 Int len = VG_(strlen)(*cpp) + preload_string_len;
204 HChar *cp = VG_(malloc)("initimg-freebsd.sce.4", len);
206 VG_(snprintf)(cp, len, "%s%s:%s",
207 ld_preload, preload_string, (*cpp)+ld_preload_len);
209 *cpp = cp;
211 ld_preload_done = True;
213 if (debug) {
214 VG_(printf)("XXXXXXXXX: MASH %s\n", *cpp);
218 /* Add the missing bits */
219 if (!ld_preload_done) {
220 Int len = ld_preload_len + preload_string_len;
221 HChar *cp = VG_(malloc) ("initimg-freebsd.sce.5", len);
223 VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
225 ret[envc++] = cp;
226 if (debug) {
227 VG_(printf)("XXXXXXXXX: ADD %s\n", cp);
231 #if defined(VGP_x86_freebsd)
232 /* If we're running a 32 bit binary, ld-elf32.so.1 may be looking for
233 * a different variable name. Or it might be a 32 bit ld-elf.so.1 in a
234 * chroot. Cover both cases. */
235 if (VG_(is32on64)()) {
236 for (cpp = ret; cpp && *cpp; cpp++) {
237 if (VG_(memcmp)(*cpp, ld_32_preload, ld_32_preload_len) == 0) {
238 Int len = VG_(strlen)(*cpp) + preload_string_len;
239 HChar *cp = VG_(malloc)("initimg-freebsd.sce.4a", len);
240 vg_assert(cp);
242 VG_(snprintf)(cp, len, "%s%s:%s",
243 ld_32_preload, preload_string, (*cpp)+ld_32_preload_len);
245 *cpp = cp;
247 ld_32_preload_done = True;
250 if (!ld_32_preload_done) {
251 Int len = ld_32_preload_len + preload_string_len;
252 HChar *cp = VG_(malloc) ("initimg-freebsd.sce.5a", len);
253 vg_assert(cp);
255 VG_(snprintf)(cp, len, "%s%s", ld_32_preload, preload_string);
257 ret[envc++] = cp;
260 #endif
262 /* ret[0 .. envc-1] is live now. */
263 /* Find and remove a binding for VALGRIND_LAUNCHER. */
264 for (i = 0; i < envc; i++) {
265 if (0 == VG_(memcmp)(ret[i], v_launcher, v_launcher_len)) {
266 break;
270 if (i < envc) {
271 for (; i < envc-1; i++) {
272 ret[i] = ret[i+1];
274 envc--;
277 VG_(free)(preload_string);
278 ret[envc] = NULL;
280 for (i = 0; i < envc; i++) {
281 if (debug) {
282 VG_(printf)("XXXXXXXXX: FINAL %s\n", ret[i]);
286 return ret;
290 /*====================================================================*/
291 /*=== Setting up the client's stack ===*/
292 /*====================================================================*/
294 /* Add a string onto the string table, and return its address */
295 static HChar *copy_str(HChar **tab, const HChar *str)
297 HChar *cp = *tab;
298 HChar *orig = cp;
300 while(*str) {
301 *cp++ = *str++;
303 *cp++ = '\0';
305 if (0) {
306 VG_(printf)("copied %p \"%s\" len %lld\n", (void*)orig, orig, (Long)(cp-orig));
309 *tab = cp;
311 return orig;
314 /* Add byte onto the string table, and return its address */
315 static HChar *copy_bytes(HChar **tab, const HChar *src, SizeT size)
317 HChar *cp = *tab;
318 /*VG_ROUNDUP(cp, sizeof(Word));*/
319 HChar *orig = cp;
321 VG_(memcpy)(cp, src, size);
323 *tab = cp+size;
325 return orig;
328 /* ----------------------------------------------------------------
330 This sets up the client's initial stack, containing the args,
331 environment and aux vector.
333 The format of the stack is:
335 higher address +-----------------+ <- clstack_end
337 : string table :
339 +-----------------+
340 | AT_NULL |
342 | auxv |
343 +-----------------+
344 | NULL |
346 | envp |
347 +-----------------+
348 | NULL |
350 | argv |
351 +-----------------+
352 | argc |
353 lower address +-----------------+ <- sp
354 | undefined |
357 Allocate and create the initial client stack. It is allocated down
358 from clstack_end, which was previously determined by the address
359 space manager. The returned value is the SP value for the client.
361 The client's auxv is created by copying and modifying our own one.
363 ---------------------------------------------------------------- */
365 static struct auxv *find_auxv(UWord* sp)
367 sp++; // skip argc (Nb: is word-sized, not int-sized!)
369 while (*sp != 0) { // skip argv
370 sp++;
372 sp++;
374 while (*sp != 0) { // skip env
375 sp++;
377 sp++;
379 return (struct auxv *)sp;
382 static Addr setup_client_stack(void* init_sp,
383 HChar** orig_envp,
384 const ExeInfo* info,
385 UInt** client_auxv,
386 Addr clstack_end,
387 SizeT clstack_max_size )
389 SysRes res;
390 HChar **cpp;
391 HChar *strtab; /* string table */
392 HChar *stringbase;
393 Addr *ptr;
394 struct auxv *auxv;
395 const struct auxv *orig_auxv;
396 const struct auxv *cauxv;
397 unsigned stringsize; /* total size of strings in bytes */
398 unsigned auxsize; /* total size of auxv in bytes */
399 Int argc; /* total argc */
400 Int envc; /* total number of env vars */
401 unsigned stacksize; /* total client stack size */
402 Addr client_SP; /* client stack base (initial SP) */
403 Addr clstack_start;
404 Int i;
405 Bool have_exename;
406 Word client_argv;
408 vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
409 vg_assert( VG_(args_for_client) );
411 const HChar *exe_name = VG_(find_executable)(VG_(args_the_exename));
412 HChar resolved_name[VKI_PATH_MAX];
413 VG_(realpath)(exe_name, resolved_name);
415 /* use our own auxv as a prototype */
416 orig_auxv = find_auxv(init_sp);
418 /* ==================== compute sizes ==================== */
420 /* first of all, work out how big the client stack will be */
421 stringsize = 0;
422 have_exename = VG_(args_the_exename) != NULL;
424 /* paste on the extra args if the loader needs them (ie, the #!
425 interpreter and its argument) */
426 argc = 0;
427 if (info->interp_name != NULL) {
428 argc++;
429 stringsize += VG_(strlen)(info->interp_name) + 1;
431 if (info->interp_args != NULL) {
432 argc++;
433 stringsize += VG_(strlen)(info->interp_args) + 1;
436 /* now scan the args we're given... */
437 if (have_exename) {
438 stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
441 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
442 argc++;
443 stringsize += VG_(strlen)( * (HChar**)
444 VG_(indexXA)( VG_(args_for_client), i ))
445 + 1;
448 /* ...and the environment */
449 envc = 0;
450 for (cpp = orig_envp; cpp && *cpp; cpp++) {
451 envc++;
452 stringsize += VG_(strlen)(*cpp) + 1;
455 Int canarylen = -1;
456 Int pagesizeslen = -1;
458 /* now, how big is the auxv? */
459 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
460 for (cauxv = orig_auxv; cauxv->a_type != VKI_AT_NULL; cauxv++) {
461 auxsize += sizeof(*cauxv);
462 switch(cauxv->a_type) {
463 case VKI_AT_EXECPATH:
464 stringsize += VG_(strlen)(resolved_name) + 1;
465 break;
466 case VKI_AT_CANARYLEN:
467 canarylen = cauxv->u.a_val;
468 /*VG_ROUNDUP(stringsize, sizeof(Word));*/
469 stringsize += canarylen;
470 break;
471 case VKI_AT_PAGESIZESLEN:
472 pagesizeslen = cauxv->u.a_val;
473 /*VG_ROUNDUP(stringsize, sizeof(Word));*/
474 stringsize += pagesizeslen;
475 break;
476 #if 0
477 case VKI_AT_TIMEKEEP:
478 /*VG_ROUNDUP(stringsize, sizeof(Word));*/
479 stringsize += sizeof(struct vki_vdso_timehands);
480 break;
481 #endif
482 #if (FREEBSD_VERS >= FREEBSD_13_0)
483 case VKI_AT_PS_STRINGS:
484 stringsize += sizeof(struct vki_ps_strings);
485 break;
486 #endif
487 #if (FREEBSD_VERS >= FREEBSD_13_1)
488 // case AT_FXRNG:
489 // case AT_KPRELOAD:
490 #endif
491 default:
492 break;
496 /* OK, now we know how big the client stack is */
497 stacksize =
498 sizeof(Word) + /* argc */
499 (have_exename ? sizeof(HChar **) : 0) + /* argc[0] == exename */
500 sizeof(HChar **)*argc + /* argv */
501 sizeof(HChar **) + /* terminal NULL */
502 sizeof(HChar **)*envc + /* envp */
503 sizeof(HChar **) + /* terminal NULL */
504 auxsize + /* auxv */
505 VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */
507 if (0) {
508 VG_(printf)("stacksize = %u\n", stacksize);
511 /* client_SP is the client's stack pointer */
512 client_SP = clstack_end - stacksize;
513 client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */
515 /* base of the string table (aligned) */
516 stringbase = strtab = (HChar *)clstack_end
517 - VG_ROUNDUP(stringsize, sizeof(int));
519 clstack_start = VG_PGROUNDDN(client_SP);
521 /* The max stack size */
522 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
524 if (0) {
525 VG_(printf)("stringsize=%u auxsize=%u stacksize=%u maxsize=0x%lx\n"
526 "clstack_start %p\n"
527 "clstack_end %p\n",
528 stringsize, auxsize, stacksize, clstack_max_size,
529 (void*)clstack_start, (void*)clstack_end);
532 /* ==================== allocate space ==================== */
535 SizeT anon_size = clstack_end - clstack_start + 1;
536 SizeT resvn_size = clstack_max_size - anon_size;
537 Addr anon_start = clstack_start;
538 Addr resvn_start = anon_start - resvn_size;
539 SizeT inner_HACK = 0;
540 Bool ok;
542 /* So far we've only accounted for space requirements down to the
543 stack pointer. If this target's ABI requires a redzone below
544 the stack pointer, we need to allocate an extra page, to
545 handle the worst case in which the stack pointer is almost at
546 the bottom of a page, and so there is insufficient room left
547 over to put the redzone in. In this case the simple thing to
548 do is allocate an extra page, by shrinking the reservation by
549 one page and growing the anonymous area by a corresponding
550 page. */
551 vg_assert(VG_STACK_REDZONE_SZB >= 0);
552 vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE);
553 if (VG_STACK_REDZONE_SZB > 0) {
554 vg_assert(resvn_size > VKI_PAGE_SIZE);
555 resvn_size -= VKI_PAGE_SIZE;
556 anon_start -= VKI_PAGE_SIZE;
557 anon_size += VKI_PAGE_SIZE;
560 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
561 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
562 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
563 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
564 vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
566 # ifdef ENABLE_INNER
567 inner_HACK = 1024*1024; // create 1M non-fault-extending stack
568 # endif
570 if (0) {
571 VG_(printf)("%#lx 0x%lx %#lx 0x%lx\n",
572 resvn_start, resvn_size, anon_start, anon_size);
575 /* Create a shrinkable reservation followed by an anonymous
576 segment. Together these constitute a growdown stack. */
577 res = VG_(mk_SysRes_Error)(0);
578 ok = VG_(am_create_reservation)(
579 resvn_start,
580 resvn_size -inner_HACK,
581 SmUpper,
582 anon_size +inner_HACK
584 if (ok) {
585 /* allocate a stack - mmap enough space for the stack */
586 res = VG_(am_mmap_anon_fixed_client)(
587 anon_start -inner_HACK,
588 anon_size +inner_HACK,
589 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
592 if ((!ok) || sr_isError(res)) {
593 /* Allocation of the stack failed. We have to stop. */
594 VG_(printf)("valgrind: "
595 "I failed to allocate space for the application's stack.\n");
596 VG_(printf)("valgrind: "
597 "This may be the result of a very large --main-stacksize=\n");
598 VG_(printf)("valgrind: setting. Cannot continue. Sorry.\n\n");
599 VG_(exit)(1);
602 vg_assert(ok);
603 vg_assert(!sr_isError(res));
605 /* Record stack extent -- needed for stack-change code. */
606 VG_(clstk_start_base) = anon_start -inner_HACK;
607 VG_(clstk_end) = VG_(clstk_start_base) + anon_size +inner_HACK -1;
611 /* ==================== create client stack ==================== */
613 ptr = (Addr*)client_SP;
615 /* --- client argc --- */
616 *ptr++ = argc + (have_exename ? 1 : 0);
618 /* --- client argv --- */
619 client_argv = (Word)ptr;
620 if (info->interp_name) {
621 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
623 if (info->interp_args) {
624 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
627 if (have_exename) {
628 *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
631 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
632 *ptr++ = (Addr)copy_str(
633 &strtab,
634 * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
637 *ptr++ = 0;
639 /* --- envp --- */
640 VG_(client_envp) = (HChar **)ptr;
641 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++) {
642 *ptr = (Addr)copy_str(&strtab, *cpp);
644 *ptr++ = 0;
646 /* --- auxv --- */
647 auxv = (struct auxv *)ptr;
648 *client_auxv = (UInt *)auxv;
649 VG_(client_auxv) = (UWord *)*client_auxv;
651 for (; orig_auxv->a_type != VKI_AT_NULL; auxv++, orig_auxv++) {
653 /* copy the entry... */
654 *auxv = *orig_auxv;
657 * ...and fix up / examine the copy
658 * in general there are thee possibilities for these items
659 * 1. copy it, a common case for scalars
660 * 2. synthesize, if the value that the host gets isn't what we want
661 * 3. ignore, usually the case for pointers to memory for the host
662 * the ignored items are just left commented out
664 switch(auxv->a_type) {
666 case VKI_AT_IGNORE:
667 case VKI_AT_PHENT:
668 case VKI_AT_PAGESZ:
669 case VKI_AT_FLAGS:
670 case VKI_AT_NOTELF:
671 case VKI_AT_UID:
672 case VKI_AT_EUID:
673 case VKI_AT_GID:
674 case VKI_AT_EGID:
675 case VKI_AT_STACKPROT:
676 case VKI_AT_NCPUS:
677 case VKI_AT_OSRELDATE:
678 case VKI_AT_PAGESIZESLEN:
679 case VKI_AT_CANARYLEN:
681 #if (FREEBSD_VERS >= FREEBSD_11)
682 // FreeBSD 11+ also have HWCAP and HWCAP2
683 case VKI_AT_EHDRFLAGS:
684 #endif
685 /* All these are pointerless, so we don't need to do
686 anything about them. */
687 break;
689 case VKI_AT_EXECPATH:
690 auxv->u.a_ptr = copy_str(&strtab, resolved_name);
691 VG_(resolved_exename) = auxv->u.a_ptr;
692 break;
693 case VKI_AT_CANARY:
694 if (canarylen >= 1) {
695 auxv->u.a_ptr = copy_bytes(&strtab, orig_auxv->u.a_ptr, canarylen);
696 } else {
697 auxv->a_type = VKI_AT_IGNORE;
699 break;
700 case VKI_AT_PAGESIZES:
701 if (pagesizeslen >= 1) {
702 auxv->u.a_ptr = copy_bytes(&strtab, orig_auxv->u.a_ptr, pagesizeslen);
703 } else {
704 auxv->a_type = VKI_AT_IGNORE;
706 break;
707 #if 0
709 * @todo PJF this crashes intermittently
711 case VKI_AT_TIMEKEEP:
712 auxv->u.a_ptr = copy_bytes(&strtab, orig_auxv->u.a_ptr, sizeof(struct vki_vdso_timehands));
713 break;
714 #endif
716 #if (FREEBSD_VERS >= FREEBSD_13_0)
717 /* @todo PJF BSDFLAGS causes serveral testcases to crash.
718 Not sure why, it seems to be used for sigfastblock */
719 // case AT_BSDFLAGS:
720 case VKI_AT_ARGC:
721 case VKI_AT_ENVC:
722 break;
723 case VKI_AT_PS_STRINGS:
724 auxv->u.a_ptr = copy_bytes(&strtab, orig_auxv->u.a_ptr, sizeof(struct vki_ps_strings));
725 ((struct vki_ps_strings*)auxv->u.a_ptr)->ps_envstr = (char**)VG_(client_envp);
726 ((struct vki_ps_strings*)auxv->u.a_ptr)->ps_argvstr = (char**)client_argv;
727 break;
728 case VKI_AT_ARGV:
729 auxv->u.a_val = client_argv;
730 break;
731 case VKI_AT_ENVV:
732 auxv->u.a_val = (Word)VG_(client_envp);
733 break;
734 #endif
736 #if (FREEBSD_VERS >= FREEBSD_13_1)
737 // I think that this is a pointer to a "fenestrasX" structture
738 // lots of stuff that I don't understand
739 // arc4random, passing through VDSO page ...
740 // case AT_FXRNG:
741 // Again a pointer, to the VDSO base for use by rtld
742 // case AT_KPRELOAD:
743 #endif
745 #if (FREEBSD_VERS >= FREEBSD_13_2)
746 case VKI_AT_USRSTACKBASE:
747 auxv->u.a_val = VG_(get_usrstack)();
748 break;
749 case VKI_AT_USRSTACKLIM:
750 auxv->u.a_val = clstack_max_size;
751 break;
752 #endif
754 case VKI_AT_PHDR:
755 if (info->phdr == 0) {
756 auxv->a_type = VKI_AT_IGNORE;
757 } else {
758 auxv->u.a_val = info->phdr;
760 break;
762 case VKI_AT_PHNUM:
763 if (info->phdr == 0) {
764 auxv->a_type = VKI_AT_IGNORE;
765 } else {
766 auxv->u.a_val = info->phnum;
768 break;
770 case VKI_AT_BASE:
771 auxv->u.a_val = info->interp_offset;
772 break;
774 case VKI_AT_ENTRY:
775 auxv->u.a_val = info->entry;
776 break;
778 default:
779 /* stomp out anything we don't know about */
780 VG_(debugLog)(2, "initimg",
781 "stomping auxv entry %llu\n",
782 (ULong)auxv->a_type);
783 auxv->a_type = VKI_AT_IGNORE;
784 break;
787 *auxv = *orig_auxv;
788 vg_assert(auxv->a_type == VKI_AT_NULL);
790 vg_assert((strtab-stringbase) == stringsize);
792 /* client_SP is pointing at client's argc/argv */
794 if (0) {
795 VG_(printf)("startup SP = %#lx\n", client_SP);
798 if (VG_(resolved_exename) == NULL) {
799 VG_(resolved_exename) = VG_(strdup)("initimg-freebsd.sre.1", resolved_name);
802 return client_SP;
806 /* Allocate the client data segment. It is an expandable anonymous
807 mapping abutting a shrinkable reservation of size max_dseg_size.
808 The data segment starts at VG_(brk_base), which is page-aligned,
809 and runs up to VG_(brk_limit), which isn't. */
811 static void setup_client_dataseg ( SizeT max_size )
813 Bool ok;
814 SysRes sres;
815 Addr anon_start = VG_(brk_base);
816 SizeT anon_size = VKI_PAGE_SIZE;
817 Addr resvn_start = anon_start + anon_size;
818 SizeT resvn_size = max_size - anon_size;
820 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
821 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
822 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
823 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
825 /* Because there's been no brk activity yet: */
826 vg_assert(VG_(brk_base) == VG_(brk_limit));
828 /* Try to create the data seg and associated reservation where
829 VG_(brk_base) says. */
830 ok = VG_(am_create_reservation)(
831 resvn_start,
832 resvn_size,
833 SmLower,
834 anon_size
837 if (!ok) {
838 /* Hmm, that didn't work. Well, let aspacem suggest an address
839 it likes better, and try again with that. */
840 anon_start = VG_(am_get_advisory_client_simple)
841 ( 0/*floating*/, anon_size+resvn_size, &ok );
842 if (ok) {
843 resvn_start = anon_start + anon_size;
844 ok = VG_(am_create_reservation)(
845 resvn_start,
846 resvn_size,
847 SmLower,
848 anon_size
850 if (ok) {
851 VG_(brk_base) = VG_(brk_limit) = anon_start;
854 /* that too might have failed, but if it has, we're hosed: there
855 is no Plan C. */
857 vg_assert(ok);
859 sres = VG_(am_mmap_anon_fixed_client)(
860 anon_start,
861 anon_size,
862 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
864 vg_assert(!sr_isError(sres));
865 vg_assert(sr_Res(sres) == anon_start);
869 /*====================================================================*/
870 /*=== TOP-LEVEL: VG_(setup_client_initial_image) ===*/
871 /*====================================================================*/
873 /* Create the client's initial memory image. */
874 IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii,
875 const VexArchInfo* vex_archinfo )
877 ExeInfo info;
878 HChar** env = NULL;
880 IIFinaliseImageInfo iifii = {
881 .clstack_max_size = 0,
882 .initial_client_SP = 0,
883 .initial_client_IP = 0,
884 .initial_client_TOC = 0,
885 .client_auxv = NULL,
886 .arch_elf_state = VKI_INIT_ARCH_ELF_STATE,
889 //--------------------------------------------------------------
890 // Load client executable, finding in $PATH if necessary
891 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
892 // p: layout_remaining_space [so there's space]
893 //--------------------------------------------------------------
894 VG_(debugLog)(1, "initimg", "Loading client\n");
896 if (VG_(args_the_exename) == NULL) {
897 VG_(err_missing_prog)();
900 VG_(memset)(&info, 0, sizeof(info));
902 load_client(&info, &iifii.initial_client_IP, &iifii.initial_client_TOC);
904 //--------------------------------------------------------------
905 // Set up client's environment
906 // p: set-libdir [for VG_(libdir)]
907 // p: get_helprequest_and_toolname [for toolname]
908 //--------------------------------------------------------------
909 VG_(debugLog)(1, "initimg", "Setup client env\n");
910 env = setup_client_env(iicii.envp, iicii.toolname);
912 //--------------------------------------------------------------
913 // Setup client stack, eip, and VG_(client_arg[cv])
914 // p: load_client() [for 'info']
915 // p: fix_environment() [for 'env']
916 //--------------------------------------------------------------
918 /* When allocating space for the client stack, take
919 notice of the --main-stacksize value. This makes it possible
920 to run programs with very large (primary) stack requirements
921 simply by specifying --main-stacksize. */
922 /* Logic is as follows:
923 - by default, use the client's current stack rlimit
924 - if that exceeds 16M, clamp to 16M
925 - if a larger --main-stacksize value is specified, use that instead
926 - in all situations, the minimum allowed stack size is 1M
928 void* init_sp = iicii.argv - 1;
929 SizeT m1 = 1024 * 1024;
930 SizeT m16 = 16 * m1;
931 SizeT szB = (SizeT)VG_(client_rlimit_stack).rlim_cur;
932 if (szB < m1) {
933 szB = m1;
935 if (szB > m16) {
936 szB = m16;
938 if (VG_(clo_main_stacksize) > 0) {
939 szB = VG_(clo_main_stacksize);
941 if (szB < m1) {
942 szB = m1;
944 szB = VG_PGROUNDUP(szB);
945 VG_(debugLog)(1, "initimg",
946 "Setup client stack: size will be %lu\n", szB);
948 iifii.clstack_max_size = szB;
950 iifii.initial_client_SP
951 = setup_client_stack( init_sp, env,
952 &info, &iifii.client_auxv,
953 iicii.clstack_end, iifii.clstack_max_size );
955 VG_(free)(env);
957 VG_(debugLog)(2, "initimg",
958 "Client info: "
959 "initial_IP=%p initial_TOC=%p brk_base=%p\n",
960 (void*)(iifii.initial_client_IP),
961 (void*)(iifii.initial_client_TOC),
962 (void*)VG_(brk_base) );
963 VG_(debugLog)(2, "initimg",
964 "Client info: "
965 "initial_SP=%p max_stack_size=%lu\n",
966 (void*)(iifii.initial_client_SP),
967 (SizeT)iifii.clstack_max_size );
970 //--------------------------------------------------------------
971 // Setup client data (brk) segment. Initially a 1-page segment
972 // which abuts a shrinkable reservation.
973 // p: load_client() [for 'info' and hence VG_(brk_base)]
974 //--------------------------------------------------------------
976 SizeT m1 = 1024 * 1024;
977 SizeT m8 = 8 * m1;
978 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
979 VG_(debugLog)(1, "initimg", "Setup client data (brk) segment\n");
980 if (dseg_max_size < m1) {
981 dseg_max_size = m1;
983 if (dseg_max_size > m8) {
984 dseg_max_size = m8;
986 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
988 setup_client_dataseg( dseg_max_size );
991 VG_(free)(info.interp_name);
992 info.interp_name = NULL;
993 VG_(free)(info.interp_args);
994 info.interp_args = NULL;
995 return iifii;
999 /*====================================================================*/
1000 /*=== TOP-LEVEL: VG_(finalise_thread1state) ===*/
1001 /*====================================================================*/
1003 /* Just before starting the client, we may need to make final
1004 adjustments to its initial image. Also we need to set up the VEX
1005 guest state for thread 1 (the root thread) and copy in essential
1006 starting values. This is handed the IIFinaliseImageInfo created by
1007 VG_(ii_create_image).
1009 void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
1011 ThreadArchState* arch = &VG_(threads)[1].arch;
1013 /* We get client_{ip/sp/toc}, and start the client with
1014 all other registers zeroed. */
1016 # if defined(VGP_x86_freebsd)
1017 vg_assert(0 == sizeof(VexGuestX86State) % 16);
1019 /* Zero out the initial state, and set up the simulated FPU in a
1020 sane way. */
1021 LibVEX_GuestX86_initialise(&arch->vex);
1023 /* Zero out the shadow areas. */
1024 VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State));
1025 VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State));
1027 /* Put essential stuff into the new state. */
1028 arch->vex.guest_ESP = iifii.initial_client_SP;
1029 arch->vex.guest_EIP = iifii.initial_client_IP;
1031 /* initialise %cs, %ds and %ss to point at the operating systems
1032 default code, data and stack segments */
1033 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1034 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1035 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
1037 # elif defined(VGP_amd64_freebsd)
1038 vg_assert(0 == sizeof(VexGuestAMD64State) % 16);
1040 /* Zero out the initial state, and set up the simulated FPU in a
1041 sane way. */
1042 LibVEX_GuestAMD64_initialise(&arch->vex);
1044 /* Zero out the shadow areas. */
1045 VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State));
1046 VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State));
1048 /* Put essential stuff into the new state. */
1049 arch->vex.guest_RSP = ((iifii.initial_client_SP - 8) & ~0xFUL) + 8;
1050 arch->vex.guest_RDI = iifii.initial_client_SP;
1051 arch->vex.guest_RIP = iifii.initial_client_IP;
1053 # else
1054 # error Unknown platform
1055 # endif
1057 /* Tell the tool that we just wrote to the registers. */
1058 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1059 sizeof(VexGuestArchState));
1061 /* Tell the tool about the client data segment and then kill it which will
1062 make it inaccessible/unaddressable. */
1063 const NSegment *seg = VG_(am_find_nsegment)(VG_(brk_base));
1064 vg_assert(seg);
1065 vg_assert(seg->kind == SkAnonC);
1066 VG_TRACK(new_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base),
1067 1/*tid*/);
1068 VG_TRACK(die_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base));
1071 #endif // defined(VGO_freebsd)
1073 /*--------------------------------------------------------------------*/
1074 /*--- ---*/
1075 /*--------------------------------------------------------------------*/