2 /*--------------------------------------------------------------------*/
3 /*--- Startup: create initial process image on FreeBSD ---*/
4 /*--- initimg-freebsd.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2009 Julian Seward
13 Copyright (C) 2018-2021 Paul Floyd
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
;
69 vg_assert( VG_(args_the_exename
) != NULL
);
70 exe_name
= VG_(find_executable
)( VG_(args_the_exename
) );
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
);
80 VG_(printf
)("valgrind: could not execute '%s'\n", exe_name
);
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
107 LD_PRELOAD=$VALGRIND_LIB/vgpreload_core-PLATFORM.so:
108 ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)?
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
)
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
;
135 Int vglib_len
= VG_(strlen
)(VG_(libdir
));
140 HChar
* preload_tool_path
;
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
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",
155 /* Determine if there's a vgpreload_<tool>_<platform>.so file, and setup
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
);
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 */
177 for (cpp
= origenv
; cpp
&& *cpp
; cpp
++) {
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 */
189 for (cpp
= ret
; *origenv
; ) {
191 VG_(printf
)("XXXXXXXXX: COPY %s\n", *origenv
);
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
);
211 ld_preload_done
= True
;
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
);
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
);
242 VG_(snprintf
)(cp
, len
, "%s%s:%s",
243 ld_32_preload
, preload_string
, (*cpp
)+ld_32_preload_len
);
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
);
255 VG_(snprintf
)(cp
, len
, "%s%s", ld_32_preload
, preload_string
);
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
)) {
271 for (; i
< envc
-1; i
++) {
277 VG_(free
)(preload_string
);
280 for (i
= 0; i
< envc
; i
++) {
282 VG_(printf
)("XXXXXXXXX: FINAL %s\n", ret
[i
]);
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
)
306 VG_(printf
)("copied %p \"%s\" len %lld\n", (void*)orig
, orig
, (Long
)(cp
-orig
));
314 /* Add byte onto the string table, and return its address */
315 static HChar
*copy_bytes(HChar
**tab
, const HChar
*src
, SizeT size
)
318 /*VG_ROUNDUP(cp, sizeof(Word));*/
321 VG_(memcpy
)(cp
, src
, size
);
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
353 lower address +-----------------+ <- sp
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
374 while (*sp
!= 0) { // skip env
379 return (struct auxv
*)sp
;
382 static Addr
setup_client_stack(void* init_sp
,
387 SizeT clstack_max_size
)
391 HChar
*strtab
; /* string table */
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) */
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 */
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) */
427 if (info
->interp_name
!= NULL
) {
429 stringsize
+= VG_(strlen
)(info
->interp_name
) + 1;
431 if (info
->interp_args
!= NULL
) {
433 stringsize
+= VG_(strlen
)(info
->interp_args
) + 1;
436 /* now scan the args we're given... */
438 stringsize
+= VG_(strlen
)( VG_(args_the_exename
) ) + 1;
441 for (i
= 0; i
< VG_(sizeXA
)( VG_(args_for_client
) ); i
++) {
443 stringsize
+= VG_(strlen
)( * (HChar
**)
444 VG_(indexXA
)( VG_(args_for_client
), i
))
448 /* ...and the environment */
450 for (cpp
= orig_envp
; cpp
&& *cpp
; cpp
++) {
452 stringsize
+= VG_(strlen
)(*cpp
) + 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;
466 case VKI_AT_CANARYLEN
:
467 canarylen
= cauxv
->u
.a_val
;
468 /*VG_ROUNDUP(stringsize, sizeof(Word));*/
469 stringsize
+= canarylen
;
471 case VKI_AT_PAGESIZESLEN
:
472 pagesizeslen
= cauxv
->u
.a_val
;
473 /*VG_ROUNDUP(stringsize, sizeof(Word));*/
474 stringsize
+= pagesizeslen
;
477 case VKI_AT_TIMEKEEP
:
478 /*VG_ROUNDUP(stringsize, sizeof(Word));*/
479 stringsize
+= sizeof(struct vki_vdso_timehands
);
482 #if (FREEBSD_VERS >= FREEBSD_13_0)
483 case VKI_AT_PS_STRINGS
:
484 stringsize
+= sizeof(struct vki_ps_strings
);
487 #if (FREEBSD_VERS >= FREEBSD_13_1)
496 /* OK, now we know how big the client stack is */
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 */
505 VG_ROUNDUP(stringsize
, sizeof(Word
)); /* strings (aligned) */
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
);
525 VG_(printf
)("stringsize=%u auxsize=%u stacksize=%u maxsize=0x%lx\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;
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
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
);
567 inner_HACK
= 1024*1024; // create 1M non-fault-extending stack
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
)(
580 resvn_size
-inner_HACK
,
582 anon_size
+inner_HACK
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");
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
);
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(
634 * (HChar
**) VG_(indexXA
)( VG_(args_for_client
), i
)
640 VG_(client_envp
) = (HChar
**)ptr
;
641 for (cpp
= orig_envp
; cpp
&& *cpp
; ptr
++, cpp
++) {
642 *ptr
= (Addr
)copy_str(&strtab
, *cpp
);
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... */
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
) {
675 case VKI_AT_STACKPROT
:
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
:
685 /* All these are pointerless, so we don't need to do
686 anything about them. */
689 case VKI_AT_EXECPATH
:
690 auxv
->u
.a_ptr
= copy_str(&strtab
, resolved_name
);
691 VG_(resolved_exename
) = auxv
->u
.a_ptr
;
694 if (canarylen
>= 1) {
695 auxv
->u
.a_ptr
= copy_bytes(&strtab
, orig_auxv
->u
.a_ptr
, canarylen
);
697 auxv
->a_type
= VKI_AT_IGNORE
;
700 case VKI_AT_PAGESIZES
:
701 if (pagesizeslen
>= 1) {
702 auxv
->u
.a_ptr
= copy_bytes(&strtab
, orig_auxv
->u
.a_ptr
, pagesizeslen
);
704 auxv
->a_type
= VKI_AT_IGNORE
;
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
));
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 */
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
;
729 auxv
->u
.a_val
= client_argv
;
732 auxv
->u
.a_val
= (Word
)VG_(client_envp
);
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 ...
741 // Again a pointer, to the VDSO base for use by rtld
745 #if (FREEBSD_VERS >= FREEBSD_13_2)
746 case VKI_AT_USRSTACKBASE
:
747 auxv
->u
.a_val
= VG_(get_usrstack
)();
749 case VKI_AT_USRSTACKLIM
:
750 auxv
->u
.a_val
= clstack_max_size
;
755 if (info
->phdr
== 0) {
756 auxv
->a_type
= VKI_AT_IGNORE
;
758 auxv
->u
.a_val
= info
->phdr
;
763 if (info
->phdr
== 0) {
764 auxv
->a_type
= VKI_AT_IGNORE
;
766 auxv
->u
.a_val
= info
->phnum
;
771 auxv
->u
.a_val
= info
->interp_offset
;
775 auxv
->u
.a_val
= info
->entry
;
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
;
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 */
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
);
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
)
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
)(
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
);
843 resvn_start
= anon_start
+ anon_size
;
844 ok
= VG_(am_create_reservation
)(
851 VG_(brk_base
) = VG_(brk_limit
) = anon_start
;
854 /* that too might have failed, but if it has, we're hosed: there
859 sres
= VG_(am_mmap_anon_fixed_client
)(
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
)
880 IIFinaliseImageInfo iifii
= {
881 .clstack_max_size
= 0,
882 .initial_client_SP
= 0,
883 .initial_client_IP
= 0,
884 .initial_client_TOC
= 0,
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;
931 SizeT szB
= (SizeT
)VG_(client_rlimit_stack
).rlim_cur
;
938 if (VG_(clo_main_stacksize
) > 0) {
939 szB
= VG_(clo_main_stacksize
);
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
);
957 VG_(debugLog
)(2, "initimg",
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",
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;
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
) {
983 if (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
;
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
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
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
;
1054 # error Unknown platform
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
));
1065 vg_assert(seg
->kind
== SkAnonC
);
1066 VG_TRACK(new_mem_brk
, VG_(brk_base
), seg
->end
+ 1 - VG_(brk_base
),
1068 VG_TRACK(die_mem_brk
, VG_(brk_base
), seg
->end
+ 1 - VG_(brk_base
));
1071 #endif // defined(VGO_freebsd)
1073 /*--------------------------------------------------------------------*/
1075 /*--------------------------------------------------------------------*/