|
From: <sv...@va...> - 2006-10-03 20:19:33
|
Author: sewardj
Date: 2006-10-03 21:19:28 +0100 (Tue, 03 Oct 2006)
New Revision: 6155
Log:
Move a lot of code to do with setting up the initial memory image on
Linux into m_initimg/initimg-linux.c (already done). Also add AIX5
getting-started stuff.
Modified:
branches/AIX5/coregrind/m_main.c
Modified: branches/AIX5/coregrind/m_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/AIX5/coregrind/m_main.c 2006-10-03 20:16:20 UTC (rev 6154)
+++ branches/AIX5/coregrind/m_main.c 2006-10-03 20:19:28 UTC (rev 6155)
@@ -29,6 +29,8 @@
*/
=20
#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
#include "pub_core_threadstate.h"
#include "pub_core_clientstate.h"
#include "pub_core_aspacemgr.h"
@@ -36,6 +38,7 @@
#include "pub_core_debuglog.h"
#include "pub_core_errormgr.h"
#include "pub_core_execontext.h"
+#include "pub_core_initimg.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
#include "pub_core_libcfile.h"
@@ -52,13 +55,21 @@
#include "pub_core_signals.h"
#include "pub_core_stacks.h" // For VG_(register_stack)
#include "pub_core_syswrap.h"
-#include "pub_core_translate.h" // For VG_(translate)
#include "pub_core_tooliface.h"
+#include "pub_core_translate.h" // For VG_(translate)
#include "pub_core_trampoline.h"
#include "pub_core_transtab.h"
-#include "pub_core_ume.h"
=20
+/* Grunge for reading AIX5 /proc/<pid>/sysent files */
+#if defined(VGO_aix5)
+ /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
+# include <sys/procfs.h> /* prsysent_t */
+ /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
+# define VG_AIX5_SYSENT_SIZE 100000
+ static UChar aix5_sysent_buf[VG_AIX5_SYSENT_SIZE];
+#endif
=20
+
/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
/*=3D=3D=3D Counters, for profiling purposes only =
=3D=3D=3D*/
/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
@@ -69,6 +80,7 @@
VG_(print_tt_tc_stats)();
VG_(print_scheduler_stats)();
VG_(print_ExeContext_stats)();
+ VG_(print_errormgr_stats)();
=20
// Memory stats
if (VG_(clo_verbosity) > 2) {
@@ -84,797 +96,6 @@
=20
=20
/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-/*=3D=3D=3D Setting up the client's environment =
=3D=3D=3D*/
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-
-/* Prepare the client's environment. This is basically a copy of our
- environment, except:
-
- LD_PRELOAD=3D$VALGRIND_LIB/vgpreload_core.so:
- ($VALGRIND_LIB/vgpreload_TOOL.so:)?
- $LD_PRELOAD
-
- If this is missing, then it is added.
-
- Also, remove any binding for VALGRIND_LAUNCHER=3D. The client should
- not be able to see this.
-
- If this needs to handle any more variables it should be hacked
- into something table driven. The copy is VG_(malloc)'d space.
-*/
-static HChar** setup_client_env ( HChar** origenv, const HChar* toolname=
)
-{
- HChar* preload_core =3D "vgpreload_core";
- HChar* ld_preload =3D "LD_PRELOAD=3D";
- HChar* v_launcher =3D VALGRIND_LAUNCHER "=3D";
- Int ld_preload_len =3D VG_(strlen)( ld_preload );
- Int v_launcher_len =3D VG_(strlen)( v_launcher );
- Bool ld_preload_done =3D False;
- Int vglib_len =3D VG_(strlen)(VG_(libdir));
-
- HChar** cpp;
- HChar** ret;
- HChar* preload_tool_path;
- Int envc, i;
-
- /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
- paths. We might not need the space for vgpreload_<tool>.so, but i=
t
- doesn't hurt to over-allocate briefly. The 16s are just cautious
- slop. */
- Int preload_core_path_len =3D vglib_len + sizeof(preload_core) + size=
of(VG_PLATFORM) + 16;
- Int preload_tool_path_len =3D vglib_len + VG_(strlen)(toolname) + siz=
eof(VG_PLATFORM) + 16;
- Int preload_string_len =3D preload_core_path_len + preload_tool_pa=
th_len;
- HChar* preload_string =3D VG_(malloc)(preload_string_len);
- vg_assert(preload_string);
-
- /* Determine if there's a vgpreload_<tool>.so file, and setup
- preload_string. */
- preload_tool_path =3D VG_(malloc)(preload_tool_path_len);
- vg_assert(preload_tool_path);
- VG_(snprintf)(preload_tool_path, preload_tool_path_len,
- "%s/%s/vgpreload_%s.so", VG_(libdir), VG_PLATFORM, tool=
name);
- if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/)=
=3D=3D 0) {
- VG_(snprintf)(preload_string, preload_string_len, "%s/%s/%s.so:%s"=
,=20
- VG_(libdir), VG_PLATFORM, preload_core, preload_tool=
_path);
- } else {
- VG_(snprintf)(preload_string, preload_string_len, "%s/%s/%s.so",=20
- VG_(libdir), VG_PLATFORM, preload_core);
- }
- VG_(free)(preload_tool_path);
-
- VG_(debugLog)(2, "main", "preload_string:\n");
- VG_(debugLog)(2, "main", " \"%s\"\n", preload_string);
-
- /* Count the original size of the env */
- envc =3D 0;
- for (cpp =3D origenv; cpp && *cpp; cpp++)
- envc++;
-
- /* Allocate a new space */
- ret =3D VG_(malloc) (sizeof(HChar *) * (envc+1+1)); /* 1 new entry + =
NULL */
- vg_assert(ret);
-
- /* copy it over */
- for (cpp =3D ret; *origenv; )
- *cpp++ =3D *origenv++;
- *cpp =3D NULL;
- =20
- vg_assert(envc =3D=3D (cpp - ret));
-
- /* Walk over the new environment, mashing as we go */
- for (cpp =3D ret; cpp && *cpp; cpp++) {
- if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) =3D=3D 0) {
- Int len =3D VG_(strlen)(*cpp) + preload_string_len;
- HChar *cp =3D VG_(malloc)(len);
- vg_assert(cp);
-
- VG_(snprintf)(cp, len, "%s%s:%s",
- ld_preload, preload_string, (*cpp)+ld_preload_len=
);
-
- *cpp =3D cp;
-
- ld_preload_done =3D True;
- }
- }
-
- /* Add the missing bits */
- if (!ld_preload_done) {
- Int len =3D ld_preload_len + preload_string_len;
- HChar *cp =3D VG_(malloc) (len);
- vg_assert(cp);
-
- VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
-
- ret[envc++] =3D cp;
- }
-
- /* ret[0 .. envc-1] is live now. */
- /* Find and remove a binding for VALGRIND_LAUNCHER. */
- for (i =3D 0; i < envc; i++)
- if (0 =3D=3D VG_(memcmp(ret[i], v_launcher, v_launcher_len)))
- break;
-
- if (i < envc) {
- for (; i < envc-1; i++)
- ret[i] =3D ret[i+1];
- envc--;
- }
-
- VG_(free)(preload_string);
- ret[envc] =3D NULL;
-
- return ret;
-}
-
-
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-/*=3D=3D=3D Setting up the client's stack =
=3D=3D=3D*/
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-
-#ifndef AT_DCACHEBSIZE
-#define AT_DCACHEBSIZE 19
-#endif /* AT_DCACHEBSIZE */
-
-#ifndef AT_ICACHEBSIZE
-#define AT_ICACHEBSIZE 20
-#endif /* AT_ICACHEBSIZE */
-
-#ifndef AT_UCACHEBSIZE
-#define AT_UCACHEBSIZE 21
-#endif /* AT_UCACHEBSIZE */
-
-#ifndef AT_SYSINFO
-#define AT_SYSINFO 32
-#endif /* AT_SYSINFO */
-
-#ifndef AT_SYSINFO_EHDR
-#define AT_SYSINFO_EHDR 33
-#endif /* AT_SYSINFO_EHDR */
-
-#ifndef AT_SECURE
-#define AT_SECURE 23 /* secure mode boolean */
-#endif /* AT_SECURE */
-
-/* Add a string onto the string table, and return its address */
-static char *copy_str(char **tab, const char *str)
-{
- char *cp =3D *tab;
- char *orig =3D cp;
-
- while(*str)
- *cp++ =3D *str++;
- *cp++ =3D '\0';
-
- if (0)
- VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-o=
rig));
-
- *tab =3D cp;
-
- return orig;
-}
-
-
-/* ----------------------------------------------------------------
-=20
- This sets up the client's initial stack, containing the args,
- environment and aux vector.
-
- The format of the stack is:
-
- higher address +-----------------+ <- clstack_end
- | |
- : string table :
- | |
- +-----------------+
- | AT_NULL |
- - -
- | auxv |
- +-----------------+
- | NULL |
- - -
- | envp |
- +-----------------+
- | NULL |
- - -
- | argv |
- +-----------------+
- | argc |
- lower address +-----------------+ <- sp
- | undefined |
- : :
-
- Allocate and create the initial client stack. It is allocated down
- from clstack_end, which was previously determined by the address
- space manager. The returned value is the SP value for the client.
-
- The client's auxv is created by copying and modifying our own one.
- As a side effect of scanning our own auxv, some important bits of
- info are collected:
-
- VG_(cache_line_size_ppc32) // ppc32 only -- cache line size
- VG_(have_altivec_ppc32) // ppc32 only -- is Altivec supported?
-
- ---------------------------------------------------------------- */
-
-static=20
-Addr setup_client_stack( void* init_sp,
- char** orig_envp,=20
- const ExeInfo* info,
- UInt** client_auxv,
- Addr clstack_end,
- SizeT clstack_max_size )
-{
- SysRes res;
- char **cpp;
- char *strtab; /* string table */
- char *stringbase;
- Addr *ptr;
- struct ume_auxv *auxv;
- const struct ume_auxv *orig_auxv;
- const struct ume_auxv *cauxv;
- unsigned stringsize; /* total size of strings in bytes */
- unsigned auxsize; /* total size of auxv in bytes */
- Int argc; /* total argc */
- Int envc; /* total number of env vars */
- unsigned stacksize; /* total client stack size */
- Addr client_SP; /* client stack base (initial SP) */
- Addr clstack_start;
- Int i;
- Bool have_exename;
-
- vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
-
- /* use our own auxv as a prototype */
- orig_auxv =3D VG_(find_auxv)(init_sp);
-
- /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D compu=
te sizes =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
-
- /* first of all, work out how big the client stack will be */
- stringsize =3D 0;
- have_exename =3D VG_(args_the_exename) !=3D NULL;
-
- /* paste on the extra args if the loader needs them (ie, the #!=20
- interpreter and its argument) */
- argc =3D 0;
- if (info->interp_name !=3D NULL) {
- argc++;
- stringsize +=3D VG_(strlen)(info->interp_name) + 1;
- }
- if (info->interp_args !=3D NULL) {
- argc++;
- stringsize +=3D VG_(strlen)(info->interp_args) + 1;
- }
-
- /* now scan the args we're given... */
- if (have_exename)
- stringsize +=3D VG_(strlen)( VG_(args_the_exename) ) + 1;
-
- for (i =3D 0; i < VG_(args_for_client).used; i++) {
- argc++;
- stringsize +=3D VG_(strlen)( VG_(args_for_client).strs[i] ) + 1;
- }
-
- /* ...and the environment */
- envc =3D 0;
- for (cpp =3D orig_envp; cpp && *cpp; cpp++) {
- envc++;
- stringsize +=3D VG_(strlen)(*cpp) + 1;
- }
-
- /* now, how big is the auxv? */
- auxsize =3D sizeof(*auxv); /* there's always at least one entry: AT_N=
ULL */
- for (cauxv =3D orig_auxv; cauxv->a_type !=3D AT_NULL; cauxv++) {
- if (cauxv->a_type =3D=3D AT_PLATFORM)
- stringsize +=3D VG_(strlen)(cauxv->u.a_ptr) + 1;
- auxsize +=3D sizeof(*cauxv);
- }
-
-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
- auxsize +=3D 2 * sizeof(*cauxv);
-# endif
-
- /* OK, now we know how big the client stack is */
- stacksize =3D
- sizeof(Word) + /* argc */
- (have_exename ? sizeof(char **) : 0) + /* argc[0] =3D=3D exename =
*/
- sizeof(char **)*argc + /* argv */
- sizeof(char **) + /* terminal NULL */
- sizeof(char **)*envc + /* envp */
- sizeof(char **) + /* terminal NULL */
- auxsize + /* auxv */
- VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */
-
- if (0) VG_(printf)("stacksize =3D %d\n", stacksize);
-
- /* client_SP is the client's stack pointer */
- client_SP =3D clstack_end - stacksize;
- client_SP =3D VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligne=
d */
-
- /* base of the string table (aligned) */
- stringbase =3D strtab =3D (char *)clstack_end=20
- - VG_ROUNDUP(stringsize, sizeof(int));
-
- clstack_start =3D VG_PGROUNDDN(client_SP);
-
- /* The max stack size */
- clstack_max_size =3D VG_PGROUNDUP(clstack_max_size);
-
- /* Record stack extent -- needed for stack-change code. */
- VG_(clstk_base) =3D clstack_start;
- VG_(clstk_end) =3D clstack_end;
-
- if (0)
- VG_(printf)("stringsize=3D%d auxsize=3D%d stacksize=3D%d maxsize=3D=
0x%x\n"
- "clstack_start %p\n"
- "clstack_end %p\n",
- stringsize, auxsize, stacksize, (Int)clstack_max_size,
- (void*)clstack_start, (void*)clstack_end);
-
- /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D alloc=
ate space =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
-
- { SizeT anon_size =3D clstack_end - clstack_start + 1;
- SizeT resvn_size =3D clstack_max_size - anon_size;
- Addr anon_start =3D clstack_start;
- Addr resvn_start =3D anon_start - resvn_size;
- SizeT inner_HACK =3D 0;
- Bool ok;
-
- /* So far we've only accounted for space requirements down to the
- stack pointer. If this target's ABI requires a redzone below
- the stack pointer, we need to allocate an extra page, to
- handle the worst case in which the stack pointer is almost at
- the bottom of a page, and so there is insufficient room left
- over to put the redzone in. In this case the simple thing to
- do is allocate an extra page, by shrinking the reservation by
- one page and growing the anonymous area by a corresponding
- page. */
- vg_assert(VG_STACK_REDZONE_SZB >=3D 0);
- vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE);
- if (VG_STACK_REDZONE_SZB > 0) {
- vg_assert(resvn_size > VKI_PAGE_SIZE);
- resvn_size -=3D VKI_PAGE_SIZE;
- anon_start -=3D VKI_PAGE_SIZE;
- anon_size +=3D VKI_PAGE_SIZE;
- }
-
- vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
- vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
- vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
- vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
- vg_assert(resvn_start =3D=3D clstack_end + 1 - clstack_max_size);
-
-# ifdef ENABLE_INNER
- inner_HACK =3D 1024*1024; // create 1M non-fault-extending stack
-# endif
-
- if (0)
- VG_(printf)("%p 0x%x %p 0x%x\n",=20
- resvn_start, resvn_size, anon_start, anon_size);
-
- /* Create a shrinkable reservation followed by an anonymous
- segment. Together these constitute a growdown stack. */
- ok =3D VG_(am_create_reservation)(
- resvn_start,
- resvn_size -inner_HACK,
- SmUpper,=20
- anon_size +inner_HACK
- );
- vg_assert(ok);
- /* allocate a stack - mmap enough space for the stack */
- res =3D VG_(am_mmap_anon_fixed_client)(
- anon_start -inner_HACK,
- anon_size +inner_HACK,
- VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
- );
- vg_assert(!res.isError);=20
- }
-
- /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D creat=
e client stack =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
*/
-
- ptr =3D (Addr*)client_SP;
-
- /* --- client argc --- */
- *ptr++ =3D argc + (have_exename ? 1 : 0);
-
- /* --- client argv --- */
- if (info->interp_name) {
- *ptr++ =3D (Addr)copy_str(&strtab, info->interp_name);
- VG_(free)(info->interp_name);
- }
- if (info->interp_args) {
- *ptr++ =3D (Addr)copy_str(&strtab, info->interp_args);
- VG_(free)(info->interp_args);
- }
-
- if (have_exename)
- *ptr++ =3D (Addr)copy_str(&strtab, VG_(args_the_exename));
-
- for (i =3D 0; i < VG_(args_for_client).used; i++) {
- *ptr++ =3D (Addr)copy_str(&strtab, VG_(args_for_client).strs[i]);
- }
- *ptr++ =3D 0;
-
- /* --- envp --- */
- VG_(client_envp) =3D (Char **)ptr;
- for (cpp =3D orig_envp; cpp && *cpp; ptr++, cpp++)
- *ptr =3D (Addr)copy_str(&strtab, *cpp);
- *ptr++ =3D 0;
-
- /* --- auxv --- */
- auxv =3D (struct ume_auxv *)ptr;
- *client_auxv =3D (UInt *)auxv;
-
-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
- auxv[0].a_type =3D AT_IGNOREPPC;
- auxv[0].u.a_val =3D AT_IGNOREPPC;
- auxv[1].a_type =3D AT_IGNOREPPC;
- auxv[1].u.a_val =3D AT_IGNOREPPC;
- auxv +=3D 2;
-# endif
-
- for (; orig_auxv->a_type !=3D AT_NULL; auxv++, orig_auxv++) {
-
- /* copy the entry... */
- *auxv =3D *orig_auxv;
-
- /* ...and fix up / examine the copy */
- switch(auxv->a_type) {
-
- case AT_IGNORE:
- case AT_PHENT:
- case AT_PAGESZ:
- case AT_FLAGS:
- case AT_NOTELF:
- case AT_UID:
- case AT_EUID:
- case AT_GID:
- case AT_EGID:
- case AT_CLKTCK:
- case AT_FPUCW:
- /* All these are pointerless, so we don't need to do
- anything about them. */
- break;
-
- case AT_PHDR:
- if (info->phdr =3D=3D 0)
- auxv->a_type =3D AT_IGNORE;
- else
- auxv->u.a_val =3D info->phdr;
- break;
-
- case AT_PHNUM:
- if (info->phdr =3D=3D 0)
- auxv->a_type =3D AT_IGNORE;
- else
- auxv->u.a_val =3D info->phnum;
- break;
-
- case AT_BASE:
- auxv->u.a_val =3D info->interp_base;
- break;
-
- case AT_PLATFORM:
- /* points to a platform description string */
- auxv->u.a_ptr =3D copy_str(&strtab, orig_auxv->u.a_ptr);
- break;
-
- case AT_ENTRY:
- auxv->u.a_val =3D info->entry;
- break;
-
- case AT_HWCAP:
- break;
-
- case AT_DCACHEBSIZE:
- case AT_ICACHEBSIZE:
- case AT_UCACHEBSIZE:
-# if defined(VGP_ppc32_linux)
- /* acquire cache info */
- if (auxv->u.a_val > 0) {
- VG_(machine_ppc32_set_clszB)( auxv->u.a_val );
- VG_(debugLog)(2, "main",=20
- "PPC32 cache line size %u (type %u)\n",=20
- (UInt)auxv->u.a_val, (UInt)auxv->a_type =
);
- }
-# elif defined(VGP_ppc64_linux)
- /* acquire cache info */
- if (auxv->u.a_val > 0) {
- VG_(machine_ppc64_set_clszB)( auxv->u.a_val );
- VG_(debugLog)(2, "main",=20
- "PPC64 cache line size %u (type %u)\n",=20
- (UInt)auxv->u.a_val, (UInt)auxv->a_type =
);
- }
-# endif
- break;
-
-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
- case AT_IGNOREPPC:
- break;
-# endif
-
- case AT_SECURE:
- /* If this is 1, then it means that this program is
- running suid, and therefore the dynamic linker should
- be careful about LD_PRELOAD, etc. However, since
- stage1 (the thing the kernel actually execve's) should
- never be SUID, and we need LD_PRELOAD to work for the
- client, we set AT_SECURE to 0. */
- auxv->u.a_val =3D 0;
- break;
-
- case AT_SYSINFO:
-# if !defined(VGP_ppc32_linux) && !defined(VGP_ppc64_linux)
- case AT_SYSINFO_EHDR:
-# endif
- /* Trash this, because we don't reproduce it */
- auxv->a_type =3D AT_IGNORE;
- break;
-
- default:
- /* stomp out anything we don't know about */
- VG_(debugLog)(2, "main",
- "stomping auxv entry %lld\n",=20
- (ULong)auxv->a_type);
- auxv->a_type =3D AT_IGNORE;
- break;
- }
- }
- *auxv =3D *orig_auxv;
- vg_assert(auxv->a_type =3D=3D AT_NULL);
-
- vg_assert((strtab-stringbase) =3D=3D stringsize);
-
- /* client_SP is pointing at client's argc/argv */
-
- if (0) VG_(printf)("startup SP =3D %p\n", client_SP);
- return client_SP;
-}
-
-
-/* Allocate the client data segment. It is an expandable anonymous
- mapping abutting a shrinkable reservation of size max_dseg_size.
- The data segment starts at VG_(brk_base), which is page-aligned,
- and runs up to VG_(brk_limit), which isn't. */
-
-static void setup_client_dataseg ( SizeT max_size )
-{
- Bool ok;
- SysRes sres;
- Addr anon_start =3D VG_(brk_base);
- SizeT anon_size =3D VKI_PAGE_SIZE;
- Addr resvn_start =3D anon_start + anon_size;
- SizeT resvn_size =3D max_size - anon_size;
-
- vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
- vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
- vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
- vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
-
- /* Because there's been no brk activity yet: */
- vg_assert(VG_(brk_base) =3D=3D VG_(brk_limit));
-
- /* Try to create the data seg and associated reservation where
- VG_(brk_base) says. */
- ok =3D VG_(am_create_reservation)(=20
- resvn_start,=20
- resvn_size,=20
- SmLower,=20
- anon_size
- );
-
- if (!ok) {
- /* Hmm, that didn't work. Well, let aspacem suggest an address
- it likes better, and try again with that. */
- anon_start =3D VG_(am_get_advisory_client_simple)
- ( 0/*floating*/, anon_size+resvn_size, &ok );
- if (ok) {
- resvn_start =3D anon_start + anon_size;
- ok =3D VG_(am_create_reservation)(=20
- resvn_start,=20
- resvn_size,=20
- SmLower,=20
- anon_size
- );
- if (ok)
- VG_(brk_base) =3D VG_(brk_limit) =3D anon_start;
- }
- /* that too might have failed, but if it has, we're hosed: there
- is no Plan C. */
- }
- vg_assert(ok);
-
- /* We make the data segment (heap) executable because LinuxThreads on
- ppc32 creates trampolines in this area. Also, on x86/Linux the da=
ta
- segment is RWX natively, at least according to /proc/self/maps.
- Also, having a non-executable data seg would kill any program whic=
h
- tried to create code in the data seg and then run it. */
- sres =3D VG_(am_mmap_anon_fixed_client)(=20
- anon_start,=20
- anon_size,=20
- VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
- );
- vg_assert(!sres.isError);
- vg_assert(sres.val =3D=3D anon_start);
-}
-
-
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-/*=3D=3D=3D Find executable =
=3D=3D=3D*/
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-
-/* Scan a colon-separated list, and call a function on each element.
- The string must be mutable, because we insert a temporary '\0', but
- the string will end up unmodified. (*func) should return True if it
- doesn't need to see any more.
-
- This routine will return True if (*func) returns True and False if
- it reaches the end of the list without that happening.
-*/
-static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
-{
- char *cp, *entry;
- int end;
-
- if (colsep =3D=3D NULL ||
- *colsep =3D=3D '\0')
- return False;
-
- entry =3D cp =3D colsep;
-
- do {
- end =3D (*cp =3D=3D '\0');
-
- if (*cp =3D=3D ':' || *cp =3D=3D '\0') {
- char save =3D *cp;
-
- *cp =3D '\0';
- if ((*func)(entry)) {
- *cp =3D save;
- return True;
- }
- *cp =3D save;
- entry =3D cp+1;
- }
- cp++;
- } while(!end);
-
- return False;
-}
-
-/* Need a static copy because can't use dynamic mem allocation yet */
-static HChar executable_name_in [VKI_PATH_MAX];
-static HChar executable_name_out[VKI_PATH_MAX];
-
-static Bool match_executable(const char *entry)=20
-{
- HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name_in) + 3];
-
- /* empty PATH element means '.' */
- if (*entry =3D=3D '\0')
- entry =3D ".";
-
- VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name_in);
-
- // Don't match directories
- if (VG_(is_dir)(buf))
- return False;
-
- // If we match an executable, we choose that immediately. If we find=
a
- // matching non-executable we remember it but keep looking for an
- // matching executable later in the path.
- if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) =3D=3D 0) {
- VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
- executable_name_out[VKI_PATH_MAX-1] =3D 0;
- return True; // Stop looking
- } else if (VG_(access)(buf, True/*r*/, False/*w*/, False/*x*/) =3D=3D=
0=20
- && VG_STREQ(executable_name_out, ""))=20
- {
- VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
- executable_name_out[VKI_PATH_MAX-1] =3D 0;
- return False; // Keep looking
- } else {=20
- return False; // Keep looking
- }
-}
-
-// Returns NULL if it wasn't found.
-static HChar* find_executable ( HChar* exec )
-{
- vg_assert(NULL !=3D exec);
- if (VG_(strchr)(exec, '/')) {
- // Has a '/' - use the name as is
- VG_(strncpy)( executable_name_out, exec, VKI_PATH_MAX-1 );
- } else {
- // No '/' - we need to search the path
- HChar* path;
- VG_(strncpy)( executable_name_in, exec, VKI_PATH_MAX-1 );
- VG_(memset) ( executable_name_out, 0, VKI_PATH_MAX );
- path =3D VG_(getenv)("PATH");
- scan_colsep(path, match_executable);
- }
- return VG_STREQ(executable_name_out, "") ? NULL : executable_name_out=
;
-}
-
-
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-/*=3D=3D=3D Command line errors =
=3D=3D=3D*/
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-
-static void revert_to_stderr ( void )
-{
- vg_assert( !VG_(logging_to_socket) );
- VG_(clo_log_fd) =3D 2; /* stderr */
-}
-
-void VG_(bad_option) ( Char* opt )
-{
- revert_to_stderr();
- VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
- VG_(printf)("valgrind: Use --help for more information.\n");
- VG_(exit)(1);
-}
-
-static void missing_prog ( void )
-{
- revert_to_stderr();
- VG_(printf)("valgrind: no program specified\n");
- VG_(printf)("valgrind: Use --help for more information.\n");
- VG_(exit)(1);
-}
-
-static void config_error ( Char* msg )
-{
- revert_to_stderr();
- VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg=
);
- VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
- VG_(exit)(1);
-}
-
-
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-/*=3D=3D=3D Loading the client =
=3D=3D=3D*/
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-
-/* Load the client whose name is VG_(argv_the_exename). */
-
-static void load_client ( /*OUT*/ExeInfo* info,=20
- /*OUT*/Addr* client_ip,
- /*OUT*/Addr* client_toc)
-{
- HChar* exe_name;
- Int ret;
- SysRes res;
-
- vg_assert( VG_(args_the_exename) !=3D NULL);
- exe_name =3D find_executable( VG_(args_the_exename) );
-
- if (!exe_name) {
- VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exen=
ame));
- VG_(exit)(127); // 127 is Posix NOTFOUND
- }
-
- VG_(memset)(info, 0, sizeof(*info));
- info->exe_base =3D VG_(client_base);
- info->exe_end =3D VG_(client_end);
-
- ret =3D VG_(do_exec)(exe_name, info);
-
- // The client was successfully loaded! Continue.
-
- /* Get hold of a file descriptor which refers to the client
- executable. This is needed for attaching to GDB. */
- res =3D VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
- if (!res.isError)
- VG_(cl_exec_fd) =3D res.val;
-
- /* Copy necessary bits of 'info' that were filled in */
- *client_ip =3D info->init_ip;
- *client_toc =3D info->init_toc;
- VG_(brk_base) =3D VG_(brk_limit) =3D VG_PGROUNDUP(info->brkbase);
-}
-
-
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
/*=3D=3D=3D Command-line: variables, processing, etc =
=3D=3D=3D*/
/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
=20
@@ -942,6 +163,7 @@
" --trace-redir=3Dno|yes show redirection details? [no]\n"
" --trace-sched=3Dno|yes show thread scheduler details? [no]\n"
" --wait-for-gdb=3Dyes|no pause on startup to wait for gdb attach=
\n"
+" --sym-offsets=3Dyes|no show syms in form 'name+offset' ? [no]\=
n"
#if 0
" --model-pthreads=3Dyes|no model the pthreads library [no]\n"
#endif
@@ -1066,8 +288,8 @@
=20
/* Check for sane path in ./configure --prefix=3D... */
if (VG_LIBDIR[0] !=3D '/')=20
- config_error("Please use absolute paths in "
- "./configure --prefix=3D... or --libdir=3D...");
+ VG_(err_config_error)("Please use absolute paths in "
+ "./configure --prefix=3D... or --libdir=3D...=
");
=20
for (i =3D 0; i < VG_(args_for_valgrind).used; i++) {
=20
@@ -1139,6 +361,7 @@
=20
else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
+ else VG_BOOL_CLO(arg, "--sym-offsets", VG_(clo_sym_offsets))
=20
else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
@@ -1202,7 +425,7 @@
VG_(message)(Vg_UserMsg, "Too many suppression files specifi=
ed.");
VG_(message)(Vg_UserMsg,=20
"Increase VG_CLO_MAX_SFILES and recompile.");
- VG_(bad_option)(arg);
+ VG_(err_bad_option)(arg);
}
VG_(clo_suppressions)[VG_(clo_n_suppressions)] =3D &arg[15];
VG_(clo_n_suppressions)++;
@@ -1216,7 +439,7 @@
if (8 !=3D VG_(strlen)(opt)) {
VG_(message)(Vg_UserMsg,=20
"--trace-flags argument must have 8 digits");
- VG_(bad_option)(arg);
+ VG_(err_bad_option)(arg);
}
for (j =3D 0; j < 8; j++) {
if ('0' =3D=3D opt[j]) { /* do nothing */ }
@@ -1224,7 +447,7 @@
else {
VG_(message)(Vg_UserMsg, "--trace-flags argument can only=
"
"contain 0s and 1s");
- VG_(bad_option)(arg);
+ VG_(err_bad_option)(arg);
}
}
}
@@ -1237,7 +460,7 @@
if (8 !=3D VG_(strlen)(opt)) {
VG_(message)(Vg_UserMsg,=20
"--profile-flags argument must have 8 digits");
- VG_(bad_option)(arg);
+ VG_(err_bad_option)(arg);
}
for (j =3D 0; j < 8; j++) {
if ('0' =3D=3D opt[j]) { /* do nothing */ }
@@ -1245,7 +468,7 @@
else {
VG_(message)(Vg_UserMsg, "--profile-flags argument can on=
ly "
"contain 0s and 1s");
- VG_(bad_option)(arg);
+ VG_(err_bad_option)(arg);
}
}
}
@@ -1261,7 +484,7 @@
=20
else if ( ! VG_(needs).command_line_options
|| ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
- VG_(bad_option)(arg);
+ VG_(err_bad_option)(arg);
}
skip_arg:
if (arg !=3D VG_(args_for_valgrind).strs[i]) {
@@ -1290,7 +513,7 @@
"--db-attach=3Dyes conflicts with --trace-children=3Dyes");
VG_(message)(Vg_UserMsg,=20
"Please choose one or the other, but not both.");
- VG_(bad_option)("--db-attach=3Dyes and --trace-children=3Dyes");
+ VG_(err_bad_option)("--db-attach=3Dyes and --trace-children=3Dyes"=
);
}
=20
if (VG_(clo_gen_suppressions) > 0 &&=20
@@ -1299,7 +522,7 @@
"Can't use --gen-suppressions=3D with this tool,");
VG_(message)(Vg_UserMsg,=20
"as it doesn't generate errors.");
- VG_(bad_option)("--gen-suppressions=3D");
+ VG_(err_bad_option)("--gen-suppressions=3D");
}
=20
/* If we've been asked to emit XML, mash around various other
@@ -1388,16 +611,16 @@
VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_T=
RUNC,=20
VKI_S_IRUSR|VKI_S_IWUSR);
if (!sres.isError) {
- tmp_log_fd =3D sres.val;
+ tmp_log_fd =3D sres.res;
break; /* for (;;) */
} else {
// If the file already existed, we try the next name. If=
it
// was some other file error, we give up.
- if (sres.val !=3D VKI_EEXIST) {
+ if (sres.err !=3D VKI_EEXIST) {
VG_(message)(Vg_UserMsg,=20
"Can't create log file '%s' (%s); giving up!",=20
- logfilename, VG_(strerror)(sres.val));
- VG_(bad_option)(
+ logfilename, VG_(strerror)(sres.err));
+ VG_(err_bad_option)(
"--log-file=3D<file> (didn't work out for some reason.)");
/*NOTREACHED*/
}
@@ -1414,12 +637,12 @@
VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,=20
VKI_S_IRUSR|VKI_S_IWUSR);
if (!sres.isError) {
- tmp_log_fd =3D sres.val;
+ tmp_log_fd =3D sres.res;
} else {
VG_(message)(Vg_UserMsg,=20
"Can't create/open log file '%s'; giving up!",=20
VG_(clo_log_name));
- VG_(bad_option)(
+ VG_(err_bad_option)(
"--log-file-exactly=3D<file> (didn't work out for some re=
ason.)");
/*NOTREACHED*/
}
@@ -1435,7 +658,7 @@
"Invalid --log-socket=3Dipaddr or --log-socket=3Dipaddr:p=
ort spec");=20
VG_(message)(Vg_UserMsg,=20
"of '%s'; giving up!", VG_(clo_log_name) );
- VG_(bad_option)(
+ VG_(err_bad_option)(
"--log-socket=3D");
/*NOTREACHED*/
}
@@ -1464,7 +687,7 @@
VG_(clo_xml) =3D False;
VG_(message)(Vg_UserMsg,=20
"%s does not support XML output.", VG_(details).name);=20
- VG_(bad_option)("--xml=3Dyes");
+ VG_(err_bad_option)("--xml=3Dyes");
/*NOTREACHED*/
}
=20
@@ -1653,7 +876,7 @@
} else {
# define BUF_LEN 256
Char version_buf[BUF_LEN];
- Int n =3D VG_(read) ( fd.val, version_buf, BUF_LEN );
+ Int n =3D VG_(read) ( fd.res, version_buf, BUF_LEN );
vg_assert(n <=3D BUF_LEN);
if (n > 0) {
version_buf[n-1] =3D '\0';
@@ -1661,7 +884,7 @@
} else {
VG_(message)(Vg_DebugMsg, " (empty?)");
}
- VG_(close)(fd.val);
+ VG_(close)(fd.res);
# undef BUF_LEN
}
=20
@@ -1688,6 +911,7 @@
static void setup_file_descriptors(void)
{
struct vki_rlimit rl;
+ Bool show =3D False;
=20
/* Get the current file descriptor limits. */
if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
@@ -1695,6 +919,20 @@
rl.rlim_max =3D 1024;
}
=20
+ if (show)
+ VG_(printf)("fd limits: host, before: cur %u max %u\n",=20
+ rl.rlim_cur, rl.rlim_max);
+
+# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ /* I don't know why this kludge is needed; however if rl.rlim_cur
+ is RLIM_INFINITY, then VG_(safe_fd)'s attempts using VG_(fcntl)
+ to lift V's file descriptors above the threshold RLIM_INFINITY -
+ N_RESERVED_FDS fail. So just use a relatively conservative
+ value in this case. */
+ if (rl.rlim_cur > 1024)
+ rl.rlim_cur =3D 1024;
+# endif
+
/* Work out where to move the soft limit to. */
if (rl.rlim_cur + N_RESERVED_FDS <=3D rl.rlim_max) {
rl.rlim_cur =3D rl.rlim_cur + N_RESERVED_FDS;
@@ -1709,96 +947,19 @@
/* Update the soft limit. */
VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
=20
+ if (show) {
+ VG_(printf)("fd limits: host, after: cur %u max %u\n",
+ rl.rlim_cur, rl.rlim_max);
+ VG_(printf)("fd limits: guest : cur %u max %u\n",
+ VG_(fd_soft_limit), VG_(fd_hard_limit));
+ }
+
if (VG_(cl_exec_fd) !=3D -1)
VG_(cl_exec_fd) =3D VG_(safe_fd)( VG_(cl_exec_fd) );
}
=20
=20
/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-/*=3D=3D=3D Initialise the first thread. =
=3D=3D=3D*/
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
-
-/* Given a pointer to the ThreadArchState for thread 1 (the root
- thread), initialise the VEX guest state, and copy in essential
- starting values.
-*/
-static void init_thread1state ( Addr client_ip,=20
- Addr client_sp,
- Addr client_toc,
- /*inout*/ ThreadArchState* arch )
-{
-#if defined(VGA_x86)
- vg_assert(0 =3D=3D sizeof(VexGuestX86State) % 8);
-
- /* Zero out the initial state, and set up the simulated FPU in a
- sane way. */
- LibVEX_GuestX86_initialise(&arch->vex);
-
- /* Zero out the shadow area. */
- VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
-
- /* Put essential stuff into the new state. */
- arch->vex.guest_ESP =3D client_sp;
- arch->vex.guest_EIP =3D client_ip;
-
- /* initialise %cs, %ds and %ss to point at the operating systems
- default code, data and stack segments */
- asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
- asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
- asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
-
-#elif defined(VGA_amd64)
- vg_assert(0 =3D=3D sizeof(VexGuestAMD64State) % 8);
-
- /* Zero out the initial state, and set up the simulated FPU in a
- sane way. */
- LibVEX_GuestAMD64_initialise(&arch->vex);
-
- /* Zero out the shadow area. */
- VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
-
- /* Put essential stuff into the new state. */
- arch->vex.guest_RSP =3D client_sp;
- arch->vex.guest_RIP =3D client_ip;
-
-#elif defined(VGA_ppc32)
- vg_assert(0 =3D=3D sizeof(VexGuestPPC32State) % 8);
-
- /* Zero out the initial state, and set up the simulated FPU in a
- sane way. */
- LibVEX_GuestPPC32_initialise(&arch->vex);
-
- /* Zero out the shadow area. */
- VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
-
- /* Put essential stuff into the new state. */
- arch->vex.guest_GPR1 =3D client_sp;
- arch->vex.guest_CIA =3D client_ip;
-
-#elif defined(VGA_ppc64)
- vg_assert(0 =3D=3D sizeof(VexGuestPPC64State) % 16);
-
- /* Zero out the initial state, and set up the simulated FPU in a
- sane way. */
- LibVEX_GuestPPC64_initialise(&arch->vex);
-
- /* Zero out the shadow area. */
- VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
-
- /* Put essential stuff into the new state. */
- arch->vex.guest_GPR1 =3D client_sp;
- arch->vex.guest_GPR2 =3D client_toc;
- arch->vex.guest_CIA =3D client_ip;
-#else
-# error Unknown arch
-#endif
- // Tell the tool that we just wrote to the registers.
- VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
- sizeof(VexGuestArchState));
-}
-
-
-/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
/*=3D=3D=3D BB profiling =
=3D=3D=3D*/
/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
=20
@@ -1942,23 +1103,24 @@
}
=20
=20
-
-Int main(Int argc, HChar **argv, HChar **envp)
+static
+Int valgrind_main ( Int argc, HChar **argv, HChar **envp,
+ ULong* ppc_aix_initial_client_intregs37,
+ void* ppc_aix_bootblock,
+ UInt ppc_aix_adler32_for_compressed_page )
{
HChar* toolname =3D "memcheck"; // default to Memcheck
- HChar** env =3D NULL;
Int need_help =3D 0; // 0 =3D no, 1 =3D --help, 2 =3D --=
help-debug
- Addr initial_client_IP =3D 0;
- Addr initial_client_SP =3D 0;
- Addr initial_client_TOC =3D 0;
Addr clstack_top =3D 0;
SizeT clstack_max_size =3D 0;
UInt* client_auxv =3D NULL;
Int loglevel, i;
Bool logging_to_fd;
struct vki_rlimit zero =3D { 0, 0 };
- ExeInfo info;
=20
+ ClientInitImgInfo ciii;
+ VG_(memset)(&ciii, 0, sizeof(ClientInitImgInfo));
+
//=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
//
// Nb: startup is complex. Prerequisites are shown at every step.
@@ -1996,6 +1158,60 @@
VERSION " debug logging\n");
=20
//--------------------------------------------------------------
+ // AIX5 only: register the system call numbers
+ // p: logging
+ // p: that the initial few syscall numbers stated in the
+ // bootblock have been installed (else we can't=20
+ // open/read/close).
+ //--------------------------------------------------------------
+# if defined(VGO_aix5)
+ VG_(debugLog)(1, "main", "aix5: registering syscalls ..\n");
+ { UChar sysent_name[50];
+ SysRes fd;
+ Bool ok;
+ Int n_unregd, sysent_used =3D 0;
+ prsysent_t* sysent_hdr;
+
+ VG_(sprintf)(sysent_name, "/proc/%d/sysent", VG_(getpid)());
+ fd =3D VG_(open)(sysent_name, VKI_O_RDONLY, 0);
+ if (fd.isError)
+ VG_(err_config_error)("aix5: can't open /proc/<pid>/sysent");
+
+ sysent_used =3D VG_(read)(fd.res, aix5_sysent_buf, VG_AIX5_SYSENT_S=
IZE);
+ if (sysent_used < 0)
+ VG_(err_config_error)("aix5: error reading /proc/<pid>/sysent");
+ if (sysent_used >=3D VG_AIX5_SYSENT_SIZE)
+ VG_(err_config_error)("aix5: VG_AIX5_SYSENT_SIZE is too low; "
+ "increase and recompile");
+ VG_(close)(fd.res);
+
+ vg_assert(sysent_used > 0 && sysent_used < VG_AIX5_SYSENT_SIZE);
+
+ sysent_hdr =3D (prsysent_t*)&aix5_sysent_buf[0];
+
+ n_unregd =3D 0;
+ for (i =3D 0; i < sysent_hdr->pr_nsyscalls; i++) {
+ UChar* name =3D &aix5_sysent_buf[ sysent_hdr
+ ->pr_syscall[i].pr_nameoff ];
+ UInt nmbr =3D sysent_hdr->pr_syscall[i].pr_number;
+ VG_(debugLog)(3, "main", "aix5: bind syscall %d to \"%s\"\n",=20
+ nmbr, name);
+ ok =3D VG_(aix5_register_syscall)(nmbr, name);
+ if (!ok)
+ n_unregd++;
+ if (!ok)
+ VG_(debugLog)(3, "main",=20
+ "aix5: bind FAILED: %d to \"%s\"\n",=20
+ nmbr, name);
+ }
+ VG_(debugLog)(1, "main", "aix5: .. %d syscalls known, %d unknown\n"=
,
+ sysent_hdr->pr_nsyscalls - n_unregd, n_unregd );
+ VG_(debugLog)(1, "main", "aix5: __NR_AIX5_FAKE_SIGRETURN =3D %d\n",
+ __NR_AIX5_FAKE_SIGRETURN );
+ }
+# endif
+
+ //--------------------------------------------------------------
// Ensure we're on a plausible stack.
// p: logging
//--------------------------------------------------------------
@@ -2149,72 +1365,35 @@
// Load client executable, finding in $PATH if necessary
// p: get_helprequest_and_toolname() [for 'exec', 'need_help']
// p: layout_remaining_space [so there's space]
- //--------------------------------------------------------------
- if (!need_help) {
- VG_(debugLog)(1, "main", "Loading client\n");
-
- if (VG_(args_the_exename) =3D=3D NULL)
- missing_prog();
-
- load_client(&info, &initial_client_IP, &initial_client_TOC);
- }
-
- //--------------------------------------------------------------
+ //
// Set up client's environment
// p: set-libdir [for VG_(libdir)]
// p: get_helprequest_and_toolname [for toolname]
- //--------------------------------------------------------------
- if (!need_help) {
- VG_(debugLog)(1, "main", "Setup client env\n");
- env =3D setup_client_env(envp, toolname);
- }
-
- //--------------------------------------------------------------
+ //
// Setup client stack, eip, and VG_(client_arg[cv])
// p: load_client() [for 'info']
// p: fix_environment() [for 'env']
- //--------------------------------------------------------------
- if (!need_help) {
- void* init_sp =3D argv - 1;
- SizeT m1 =3D 1024 * 1024;
- SizeT m16 =3D 16 * m1;
- VG_(debugLog)(1, "main", "Setup client stack\n");
- clstack_max_size =3D (SizeT)VG_(client_rlimit_stack).rlim_cur;
- if (clstack_max_size < m1) clstack_max_size =3D m1;
- if (clstack_max_size > m16) clstack_max_size =3D m16;
- clstack_max_size =3D VG_PGROUNDUP(clstack_max_size);
-
- initial_client_SP
- =3D setup_client_stack( init_sp, env,=20
- &info, &client_auxv,=20
- clstack_top, clstack_max_size );
-
- VG_(free)(env);
-
- VG_(debugLog)(2, "main",
- "Client info: "
- "initial_IP=3D%p initial_SP=3D%p initial_TOC=3D%p=
brk_base=3D%p\n",
- (void*)initial_client_IP,=20
- (void*)initial_client_SP,
- (void*)initial_client_TOC,
- (void*)VG_(brk_base) );
- }
-
- //--------------------------------------------------------------
+ //
// Setup client data (brk) segment. Initially a 1-page segment
// which abuts a shrinkable reservation.=20
// p: load_client() [for 'info' and hence VG_(brk_base)]
//--------------------------------------------------------------
- if (!need_help) {=20
- SizeT m1 =3D 1024 * 1024;
- SizeT m8 =3D 8 * m1;
- SizeT dseg_max_size =3D (SizeT)VG_(client_rlimit_data).rlim_cur;
- VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
- if (dseg_max_size < m1) dseg_max_size =3D m1;
- if (dseg_max_size > m8) dseg_max_size =3D m8;
- dseg_max_size =3D VG_PGROUNDUP(dseg_max_size);
-
- setup_client_dataseg( dseg_max_size );
+ if (!need_help) {
+ VG_(debugLog)(1, "main", "Setting up initial image\n");
+ ciii =3D VG_(setup_client_initial_image)(=20
+ argv, envp, toolname,=20
+ clstack_top, clstack_max_size=20
+ );
+# if defined(VGO_aix5)
+ ciii.adler32_exp =3D ppc_aix_adler32_for_compressed_page;
+ ciii.compressed_page =3D VG_PGROUNDDN((Addr)ppc_aix_bootblock);
+ ciii.intregs37 =3D ppc_aix_initial_client_intregs37;
+ ciii.initial_client_SP =3D ciii.intregs37[1]; /* r1 */
+ /* Tell aspacem where the initial client stack is, so that it
+ can later produce a faked-up NSegment in response to
+ VG_(am_find_nsegment) for that address range, if asked. */
+ VG_(am_aix5_set_initial_client_sp)( ciii.initial_client_SP );
+# endif
}
=20
//=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
@@ -2247,12 +1426,11 @@
VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
fd =3D VG_(mkstemp)( buf, buf2 );
if (fd =3D=3D -1)
- config_error("Can't create client cmdline file in /tmp.");
+ VG_(err_config_error)("Can't create client cmdline file in /tmp=
.");
=20
nul[0] =3D 0;
exename =3D VG_(args_the_exename) ? VG_(args_the_exename)
: "unknown_exename";
-
VG_(write)(fd, VG_(args_the_exename),=20
VG_(strlen)( VG_(args_the_exename) ));
VG_(write)(fd, nul, 1);
@@ -2270,7 +1448,7 @@
/* Now delete it, but hang on to the fd. */
r =3D VG_(unlink)( buf2 );
if (r)
- config_error("Can't delete client cmdline file in /tmp.");
+ VG_(err_config_error)("Can't delete client cmdline file in /tmp=
.");
=20
VG_(cl_cmdline_fd) =3D fd;
}
@@ -2364,11 +1542,6 @@
Long q, iters;
VG_(debugLog)(1, "main", "Wait for GDB\n");
VG_(printf)("pid=3D%d, entering delay loop\n", VG_(getpid)());
- /* jrs 20050206: I don't understand why this works on x86. On
- amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
- work. */
- /* do "jump *$eip" to skip this in gdb (x86) */
- //VG_(do_syscall0)(__NR_pause);
=20
# if defined(VGP_x86_linux)
iters =3D 5;
@@ -2376,8 +1549,10 @@
iters =3D 10;
# elif defined(VGP_ppc32_linux)
iters =3D 5;
+# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ iters =3D 4;
# else
-# error "Unknown plat"
+# error "Unknown plat"
# endif
=20
iters *=3D 1000*1000*1000;
@@ -2401,11 +1576,12 @@
// p: probably: setup fds and process CLOs, so that logging works
//--------------------------------------------------------------
VG_(debugLog)(1, "main", "Load initial debug info\n");
+# if defined(VGO_linux)
{ Addr* seg_starts;
Int n_seg_starts;
=20
seg_starts =3D get_seg_starts( &n_seg_starts );
- vg_assert(seg_starts && n_seg_starts > 0);
+ vg_assert(seg_starts && n_seg_starts >=3D 0);
=20
/* show them all to the debug info reader. allow_SkFileV has to
be True here so that we read info from the valgrind executable
@@ -2415,7 +1591,39 @@
=20
VG_(free)( seg_starts );
}
+# elif defined(VGO_aix5)
+ { AixCodeSegChange* changes;
+ Int changes_size, changes_used;
=20
+ /* Find out how many AixCodeSegChange records we will need,
+ and acquire them. */
+ changes_size =3D VG_(am_aix5_reread_procmap_howmany_directives)();=20
+ changes =3D VG_(malloc)(changes_size * sizeof(AixCodeSegChange));
+ vg_assert(changes);
+
+ /* Now re-read /proc/<pid>/map and acquire a change set */
+ VG_(am_aix5_reread_procmap)( changes, &changes_used );
+ vg_assert(changes_used >=3D 0 && changes_used <=3D changes_size);
+
+ /* And notify m_debuginfo of the changes. */
+ for (i =3D 0; i < changes_used; i++)
+ VG_(di_aix5_notify_segchange)(
+ changes[i].code_start,
+ changes[i].code_len,
+ changes[i].data_start,
+ changes[i].data_len,
+ changes[i].file_name,
+ changes[i].mem_name,
+ changes[i].is_mainexe,
+ changes[i].acquire
+ );
+
+ VG_(free)(changes);
+ }
+# else
+# error Unknown OS
+# endif
+
//--------------------------------------------------------------
// Tell aspacem of ownership change of the asm helpers, so that
// m_translate allows them to be translated. However, only do this
@@ -2445,14 +1653,14 @@
VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
{ Addr* seg_starts;
Int n_seg_starts;
- NSegment* seg;
=20
seg_starts =3D get_seg_starts( &n_seg_starts );
- vg_assert(seg_starts && n_seg_starts > 0);
+ vg_assert(seg_starts && n_seg_starts >=3D 0);
=20
/* show interesting ones to the tool */
for (i =3D 0; i < n_seg_starts; i++) {
- seg =3D VG_(am_find_nsegment)( seg_starts[i] );
+ NSegment const*const seg=20
+ =3D VG_(am_find_nsegment)( seg_starts[i] );
vg_assert(seg);
if (seg->kind =3D=3D SkFileC || seg->kind =3D=3D SkAnonC) {
VG_(debugLog)(2, "main",=20
@@ -2469,22 +1677,31 @@
VG_(free)( seg_starts );
=20
/* Also do the initial stack permissions. */
- seg =3D VG_(am_find_nsegment)( initial_client_SP );
- vg_assert(seg);
- vg_assert(seg->kind =3D=3D SkAnonC);
- vg_assert(initial_client_SP >=3D seg->start);
- vg_assert(initial_client_SP <=3D seg->end);
+ { NSegment const*const seg=20
+ =3D VG_(am_find_nsegment)( ciii.initial_client_SP );
+ vg_assert(seg);
+ vg_assert(seg->kind =3D=3D SkAnonC);
+ vg_assert(ciii.initial_client_SP >=3D seg->start);
+ vg_assert(ciii.initial_client_SP <=3D seg->end);
+# if defined(VGO_aix5)
+ VG_(clstk_base) =3D seg->start;
+ VG_(clstk_end) =3D seg->end;
+# endif
=20
- /* Stuff below the initial SP is unaddressable. Take into
- account any ABI-mandated space below the stack pointer that is
- required (VG_STACK_REDZONE_SZB). setup_client_stack() will
- have allocated an extra page if a red zone is required, to be on=20
- the safe side. */
- vg_assert(initial_client_SP - VG_STACK_REDZONE_SZB >=3D seg->start)=
;
- VG_TRACK( die_mem_stack, seg->start, initial_client_SP=20
- - VG_STACK_REDZONE_SZB - seg->=
start );
- VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
- seg->start, initial_client_SP-1 - VG_STACK_REDZONE=
_SZB);
+ /* Stuff below the initial SP is unaddressable. Take into
+ account any ABI-mandated space below the stack pointer that
+ is required (VG_STACK_REDZONE_SZB). setup_client_stack()
+ will have allocated an extra page if a red zone is required,
+ to be on the safe side. */
+ vg_assert(ciii.initial_client_SP - VG_STACK_REDZONE_SZB >=3D seg-=
>start);
+ VG_TRACK( die_mem_stack,=20
+ seg->start,=20
+ ciii.initial_client_SP - VG_STACK_REDZONE_SZB=20
+ - seg->start );
+ VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n=
",
+ seg->start,=20
+ ciii.initial_client_SP-1 - VG_STACK_REDZONE_SZB)=
;
+ }
=20
/* Also the assembly helpers. */
VG_TRACK( new_mem_startup,
@@ -2502,26 +1719,24 @@
// p: setup_client_stack
//--------------------------------------------------------------
VG_(debugLog)(1, "main", "Initialise scheduler\n");
- { NSegment* seg =3D VG_(am_find_nsegment)( initial_client_SP );
+ { NSegment const*const seg=20
+ =3D VG_(am_find_nsegment)( ciii.initial_client_SP );
vg_assert(seg);
vg_assert(seg->kind =3D=3D SkAnonC);
- vg_assert(initial_client_SP >=3D seg->start);
- vg_assert(initial_client_SP <=3D seg->end);
+ vg_assert(ciii.initial_client_SP >=3D seg->start);
+ vg_assert(ciii.initial_client_SP <=3D seg->end);
VG_(scheduler_init)( seg->end, clstack_max_size );
}
=20
//--------------------------------------------------------------
- // Initialise the pthread model
+ // Set up state for the root thread
// p: ?
- // load_client() [for 'client_eip']
- // setup_client_stack() [for 'sp_at_startup']
- // setup_scheduler() [for the rest of state 1 stuff]
+ // setup_scheduler() [for sched-specific thread 1 stuff]
+ // VG_(setup_client_initial_image)
+ // [for 'ciii' initial layout info]
//--------------------------------------------------------------
- VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
- init_thread1state( initial_client_IP,=20
- initial_client_SP,=20
- initial_client_TOC,
- &VG_(threads)[1].arch);
+ VG_(debugLog)(1, "main", "Finalise thread 1's state\n");
+ VG_(finalise_thread1state)( &VG_(threads)[1].arch, ciii );
=20
//--------------------------------------------------------------
// Initialise the pthread model
@@ -2598,31 +1813,75 @@
vg_assert(0);
}
=20
-/* Do everything which needs doing when the last thread exits. */
+/* Do everything which needs doing when the last thread exits or when
+ a thread exits requesting a complete process exit (exit on AIX).
=20
+ We enter here holding The Lock. For the case VgSrc_ExitProcess we
+ must never release it, because to do so would allow other threads
+ to continue after the system is ostensibly shut down. So we must
+ go to our grave, so to speak, holding the lock.=20
+
+ In fact, there is never any point in releasing the lock at this
+ point - we have it, we're shutting down the entire system, and
+ for the case VgSrc_ExitProcess doing so positively causes trouble.
+ So don't.=20
+
+ The final_tidyup call makes a bit of a nonsense of the ExitProcess
+ case, since it will run the libc_freeres function, thus allowing
+ other lurking threads to run again. Hmm. */
+
static=20
void shutdown_actions_NORETURN( ThreadId tid,=20
VgSchedReturnCode tids_schedretcode )
{
VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n")=
;
+ VG_(am_show_nsegments)(1,"Memory layout at client shutdown");
=20
- vg_assert( VG_(count_living_threads)() =3D=3D 1 );
vg_assert(VG_(is_running_thread)(tid));
=20
- ...
[truncated message content] |