From d4577533d1f7d24bc0b94c9bd8ce95e86da12261 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Fri, 17 Nov 2006 20:00:57 +0000 Subject: [PATCH] Redo the interface to m_initimg (module for setting up the initial client image) so it's less of an incomprehensible mess. Basically the idea is to have two standard functions, VG_(ii_create_image) and VG_(ii_finalise_image), which communicate using the structure types IICreateImageInfo and IIFinaliseImageInfo. The types hold various OS-specific bits of info. A nice side effect is that m_main is tidied up somewhat. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6357 --- coregrind/m_initimg/initimg-aix5.c | 168 ++++++++++++++-------------- coregrind/m_initimg/initimg-linux.c | 81 +++++++------- coregrind/m_main.c | 143 ++++++++++++++--------- coregrind/m_scheduler/scheduler.c | 4 + coregrind/pub_core_initimg.h | 134 ++++++++++++++-------- 5 files changed, 309 insertions(+), 221 deletions(-) diff --git a/coregrind/m_initimg/initimg-aix5.c b/coregrind/m_initimg/initimg-aix5.c index a1d3b1671a..affb74532f 100644 --- a/coregrind/m_initimg/initimg-aix5.c +++ b/coregrind/m_initimg/initimg-aix5.c @@ -61,17 +61,8 @@ static void diagnose_load_failure ( void ); /* --- Create the client's initial memory image. --- */ -ClientInitImgInfo - VG_(setup_client_initial_image)( - /*IN*/ HChar** argv, - /*IN*/ HChar** envp, - /*IN*/ HChar* toolname, - /*IN*/ Addr clstack_top, - /*IN*/ SizeT clstack_max_size - ) +IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii ) { - ClientInitImgInfo ciii; - /* Set up an AIX5PreloadPage structure with the names of $VALGRIND_LIB/PLATFORM/vgpreload_core.so @@ -101,13 +92,16 @@ ClientInitImgInfo Int szB, szPG; SysRes sres; - vg_assert( toolname ); + IIFinaliseImageInfo iifii; + VG_(memset)( &iifii, 0, sizeof(iifii) ); + + vg_assert( iicii.toolname ); pltool_len = VG_(strlen)( VG_(libdir) ) + 1 /*slash*/ + VG_(strlen)(VG_PLATFORM) + 1 /*slash*/ + VG_(strlen)( vgpreload_ ) - + VG_(strlen)( toolname ) + + VG_(strlen)( iicii.toolname ) + VG_(strlen)( _so ) + 1 /*NUL*/; vg_assert(pltool_len > 0); @@ -118,7 +112,7 @@ ClientInitImgInfo VG_(strcat)( pltool_str, VG_PLATFORM ); VG_(strcat)( pltool_str, "/" ); VG_(strcat)( pltool_str, vgpreload_ ); - VG_(strcat)( pltool_str, toolname ); + VG_(strcat)( pltool_str, iicii.toolname ); VG_(strcat)( pltool_str, _so ); vg_assert( pltool_str[pltool_len-1] == 0); vg_assert( VG_(strlen)(pltool_str) == pltool_len-1 ); @@ -178,7 +172,8 @@ ClientInitImgInfo + (have_ld_pre ? ld_pre_len : 0) + errmsg_len; szPG = VG_PGROUNDUP(szB+1) / VKI_PAGE_SIZE; - VG_(debugLog)(2, "initimg", "preload page size: %d bytes, %d pages\n", szB, szPG); + VG_(debugLog)(2, "initimg", + "preload page size: %d bytes, %d pages\n", szB, szPG); vg_assert(szB > 0); vg_assert(szB < szPG * VKI_PAGE_SIZE); @@ -239,9 +234,13 @@ ClientInitImgInfo pp->p_diagnose_load_failure = &diagnose_load_failure; - ciii.preloadpage = pp; - ciii.intregs37 = 0; /* filled in in m_main.c */ - return ciii; + iifii.preloadpage = pp; + iifii.intregs37 = iicii.intregs37; + iifii.initial_client_SP = iicii.intregs37[1]; /* r1 */ + iifii.compressed_page = VG_PGROUNDDN((Addr)iicii.bootblock); + iifii.adler32_exp = iicii.adler32_exp; + iifii.clstack_max_size = 0; /* we don't know yet */ + return iifii; } @@ -265,15 +264,22 @@ static UInt compute_adler32 ( void* addr, UWord len ) return (s2 << 16) + s1; } -void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, - ClientInitImgInfo ciii ) +/* Just before starting the client, we may need to make final + adjustments to its initial image. Also we need to set up the VEX + guest state for thread 1 (the root thread) and copy in essential + starting values. This is handed the IIFinaliseImageInfo created by + VG_(ii_create_image). +*/ +void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) { - UInt adler32_act; + UInt adler32_act; SysRes sres; /* On AIX we get a block of 37 words telling us the initial state for (GPR0 .. GPR31, PC, CR, LR, CTR, XER), and we start with all the other registers zeroed. */ + ThreadArchState* arch = &VG_(threads)[1].arch; + # if defined(VGP_ppc32_aix5) vg_assert(0 == sizeof(VexGuestPPC32State) % 8); @@ -298,61 +304,61 @@ void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, # endif - /* ciii.intregs37 contains the integer register state as it needs + /* iifii.intregs37 contains the integer register state as it needs to be at client startup. These values are supplied by the launcher. The 37 regs are:initial values from launcher for: GPR0 .. GPR31, PC, CR, LR, CTR, XER. */ /* Put essential stuff into the new state. */ - arch->vex.guest_GPR0 = (UWord)ciii.intregs37[0]; - arch->vex.guest_GPR1 = (UWord)ciii.intregs37[1]; - arch->vex.guest_GPR2 = (UWord)ciii.intregs37[2]; - arch->vex.guest_GPR3 = (UWord)ciii.intregs37[3]; - arch->vex.guest_GPR4 = (UWord)ciii.intregs37[4]; - arch->vex.guest_GPR5 = (UWord)ciii.intregs37[5]; - arch->vex.guest_GPR6 = (UWord)ciii.intregs37[6]; - arch->vex.guest_GPR7 = (UWord)ciii.intregs37[7]; - arch->vex.guest_GPR8 = (UWord)ciii.intregs37[8]; - arch->vex.guest_GPR9 = (UWord)ciii.intregs37[9]; - arch->vex.guest_GPR10 = (UWord)ciii.intregs37[10]; - arch->vex.guest_GPR11 = (UWord)ciii.intregs37[11]; - arch->vex.guest_GPR12 = (UWord)ciii.intregs37[12]; - arch->vex.guest_GPR13 = (UWord)ciii.intregs37[13]; - arch->vex.guest_GPR14 = (UWord)ciii.intregs37[14]; - arch->vex.guest_GPR15 = (UWord)ciii.intregs37[15]; - arch->vex.guest_GPR16 = (UWord)ciii.intregs37[16]; - arch->vex.guest_GPR17 = (UWord)ciii.intregs37[17]; - arch->vex.guest_GPR18 = (UWord)ciii.intregs37[18]; - arch->vex.guest_GPR19 = (UWord)ciii.intregs37[19]; - arch->vex.guest_GPR20 = (UWord)ciii.intregs37[20]; - arch->vex.guest_GPR21 = (UWord)ciii.intregs37[21]; - arch->vex.guest_GPR22 = (UWord)ciii.intregs37[22]; - arch->vex.guest_GPR23 = (UWord)ciii.intregs37[23]; - arch->vex.guest_GPR24 = (UWord)ciii.intregs37[24]; - arch->vex.guest_GPR25 = (UWord)ciii.intregs37[25]; - arch->vex.guest_GPR26 = (UWord)ciii.intregs37[26]; - arch->vex.guest_GPR27 = (UWord)ciii.intregs37[27]; - arch->vex.guest_GPR28 = (UWord)ciii.intregs37[28]; - arch->vex.guest_GPR29 = (UWord)ciii.intregs37[29]; - arch->vex.guest_GPR30 = (UWord)ciii.intregs37[30]; - arch->vex.guest_GPR31 = (UWord)ciii.intregs37[31]; - - arch->vex.guest_CIA = (UWord)ciii.intregs37[32+0]; - arch->vex.guest_LR = (UWord)ciii.intregs37[32+2]; - arch->vex.guest_CTR = (UWord)ciii.intregs37[32+3]; + arch->vex.guest_GPR0 = (UWord)iifii.intregs37[0]; + arch->vex.guest_GPR1 = (UWord)iifii.intregs37[1]; + arch->vex.guest_GPR2 = (UWord)iifii.intregs37[2]; + arch->vex.guest_GPR3 = (UWord)iifii.intregs37[3]; + arch->vex.guest_GPR4 = (UWord)iifii.intregs37[4]; + arch->vex.guest_GPR5 = (UWord)iifii.intregs37[5]; + arch->vex.guest_GPR6 = (UWord)iifii.intregs37[6]; + arch->vex.guest_GPR7 = (UWord)iifii.intregs37[7]; + arch->vex.guest_GPR8 = (UWord)iifii.intregs37[8]; + arch->vex.guest_GPR9 = (UWord)iifii.intregs37[9]; + arch->vex.guest_GPR10 = (UWord)iifii.intregs37[10]; + arch->vex.guest_GPR11 = (UWord)iifii.intregs37[11]; + arch->vex.guest_GPR12 = (UWord)iifii.intregs37[12]; + arch->vex.guest_GPR13 = (UWord)iifii.intregs37[13]; + arch->vex.guest_GPR14 = (UWord)iifii.intregs37[14]; + arch->vex.guest_GPR15 = (UWord)iifii.intregs37[15]; + arch->vex.guest_GPR16 = (UWord)iifii.intregs37[16]; + arch->vex.guest_GPR17 = (UWord)iifii.intregs37[17]; + arch->vex.guest_GPR18 = (UWord)iifii.intregs37[18]; + arch->vex.guest_GPR19 = (UWord)iifii.intregs37[19]; + arch->vex.guest_GPR20 = (UWord)iifii.intregs37[20]; + arch->vex.guest_GPR21 = (UWord)iifii.intregs37[21]; + arch->vex.guest_GPR22 = (UWord)iifii.intregs37[22]; + arch->vex.guest_GPR23 = (UWord)iifii.intregs37[23]; + arch->vex.guest_GPR24 = (UWord)iifii.intregs37[24]; + arch->vex.guest_GPR25 = (UWord)iifii.intregs37[25]; + arch->vex.guest_GPR26 = (UWord)iifii.intregs37[26]; + arch->vex.guest_GPR27 = (UWord)iifii.intregs37[27]; + arch->vex.guest_GPR28 = (UWord)iifii.intregs37[28]; + arch->vex.guest_GPR29 = (UWord)iifii.intregs37[29]; + arch->vex.guest_GPR30 = (UWord)iifii.intregs37[30]; + arch->vex.guest_GPR31 = (UWord)iifii.intregs37[31]; + + arch->vex.guest_CIA = (UWord)iifii.intregs37[32+0]; + arch->vex.guest_LR = (UWord)iifii.intregs37[32+2]; + arch->vex.guest_CTR = (UWord)iifii.intregs37[32+3]; # if defined(VGP_ppc32_aix5) - LibVEX_GuestPPC32_put_CR( (UWord)ciii.intregs37[32+1], &arch->vex ); - LibVEX_GuestPPC32_put_XER( (UWord)ciii.intregs37[32+4], &arch->vex ); + LibVEX_GuestPPC32_put_CR( (UWord)iifii.intregs37[32+1], &arch->vex ); + LibVEX_GuestPPC32_put_XER( (UWord)iifii.intregs37[32+4], &arch->vex ); /* Set the cache line size (KLUDGE) */ VG_(machine_ppc32_set_clszB)( 128 ); # else /* defined(VGP_ppc64_aix5) */ - LibVEX_GuestPPC64_put_CR( (UWord)ciii.intregs37[32+1], &arch->vex ); - LibVEX_GuestPPC64_put_XER( (UWord)ciii.intregs37[32+4], &arch->vex ); + LibVEX_GuestPPC64_put_CR( (UWord)iifii.intregs37[32+1], &arch->vex ); + LibVEX_GuestPPC64_put_XER( (UWord)iifii.intregs37[32+4], &arch->vex ); /* Set the cache line size (KLUDGE) */ VG_(machine_ppc64_set_clszB)( 128 ); @@ -382,22 +388,22 @@ void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, /* At this point the guest register state is correct for client startup. However, that's not where we want to start; in fact we - want to start at VG_(ppc{3,64}2_aix5_do_preloads_then_start_client), - passing it ciii.preloadpage in r3. This will load the core/tool + want to start at VG_(ppc{32,64}_aix5_do_preloads_then_start_client), + passing it iifii.preloadpage in r3. This will load the core/tool preload .so's, then restore r2-r10 from what's stashed in the preloadpage, and then start the client really. Hence: */ /* Save r2-r10 and the client start point in preloadpage */ - ciii.preloadpage->r2 = (ULong)arch->vex.guest_GPR2; - ciii.preloadpage->r3 = (ULong)arch->vex.guest_GPR3; - ciii.preloadpage->r4 = (ULong)arch->vex.guest_GPR4; - ciii.preloadpage->r5 = (ULong)arch->vex.guest_GPR5; - ciii.preloadpage->r6 = (ULong)arch->vex.guest_GPR6; - ciii.preloadpage->r7 = (ULong)arch->vex.guest_GPR7; - ciii.preloadpage->r8 = (ULong)arch->vex.guest_GPR8; - ciii.preloadpage->r9 = (ULong)arch->vex.guest_GPR9; - ciii.preloadpage->r10 = (ULong)arch->vex.guest_GPR10; - ciii.preloadpage->client_start = (ULong)arch->vex.guest_CIA; + iifii.preloadpage->r2 = (ULong)arch->vex.guest_GPR2; + iifii.preloadpage->r3 = (ULong)arch->vex.guest_GPR3; + iifii.preloadpage->r4 = (ULong)arch->vex.guest_GPR4; + iifii.preloadpage->r5 = (ULong)arch->vex.guest_GPR5; + iifii.preloadpage->r6 = (ULong)arch->vex.guest_GPR6; + iifii.preloadpage->r7 = (ULong)arch->vex.guest_GPR7; + iifii.preloadpage->r8 = (ULong)arch->vex.guest_GPR8; + iifii.preloadpage->r9 = (ULong)arch->vex.guest_GPR9; + iifii.preloadpage->r10 = (ULong)arch->vex.guest_GPR10; + iifii.preloadpage->client_start = (ULong)arch->vex.guest_CIA; # if defined(VGP_ppc32_aix5) @@ -412,29 +418,29 @@ void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, # endif - arch->vex.guest_GPR3 = (UWord)ciii.preloadpage; + arch->vex.guest_GPR3 = (UWord)iifii.preloadpage; /* The rest of the preloadpage fields will already have been filled in by VG_(setup_client_initial_image). So we're done. */ /* Finally, decompress the page compressed by the launcher. We can't do this any earlier, because the page is (effectively) - decompressed in place, which trashes ciii.intregs37. So we have - to wait till this point, at which we're done with ciii.intregs37 + decompressed in place, which trashes iifii.intregs37. So we have + to wait till this point, at which we're done with iifii.intregs37 (to be precise, with what it points at). */ VG_(debugLog)(1, "initimg", "decompressing page at %p\n", - (void*)ciii.compressed_page); - vg_assert(VG_IS_PAGE_ALIGNED(ciii.compressed_page)); + (void*)iifii.compressed_page); + vg_assert(VG_IS_PAGE_ALIGNED(iifii.compressed_page)); - Huffman_Uncompress( (void*)ciii.compressed_page, unz_page, + Huffman_Uncompress( (void*)iifii.compressed_page, unz_page, VKI_PAGE_SIZE, VKI_PAGE_SIZE ); adler32_act = compute_adler32(unz_page, VKI_PAGE_SIZE); VG_(debugLog)(1, "initimg", "decompress done, adler32s: act 0x%x, exp 0x%x\n", - adler32_act, ciii.adler32_exp ); + adler32_act, iifii.adler32_exp ); - VG_(memcpy)((void*)ciii.compressed_page, unz_page, VKI_PAGE_SIZE); + VG_(memcpy)((void*)iifii.compressed_page, unz_page, VKI_PAGE_SIZE); VG_(debugLog)(1, "initimg", "copy back done\n"); diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c index 5f04857aac..15f576049e 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -818,19 +818,13 @@ static void setup_client_dataseg ( SizeT max_size ) /*====================================================================*/ /* Create the client's initial memory image. */ - -ClientInitImgInfo - VG_(setup_client_initial_image)( - /*IN*/ HChar** argv, - /*IN*/ HChar** envp, - /*IN*/ HChar* toolname, - /*IN*/ Addr clstack_top, - /*IN*/ SizeT clstack_max_size - ) +IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii ) { - ClientInitImgInfo ciii = { 0, 0, 0, NULL }; - ExeInfo info; - HChar** env = NULL; + ExeInfo info; + HChar** env = NULL; + + IIFinaliseImageInfo iifii; + VG_(memset)( &iifii, 0, sizeof(iifii) ); //-------------------------------------------------------------- // Load client executable, finding in $PATH if necessary @@ -842,7 +836,7 @@ ClientInitImgInfo if (VG_(args_the_exename) == NULL) VG_(err_missing_prog)(); - load_client(&info, &ciii.initial_client_IP, &ciii.initial_client_TOC); + load_client(&info, &iifii.initial_client_IP, &iifii.initial_client_TOC); //-------------------------------------------------------------- // Set up client's environment @@ -850,7 +844,7 @@ ClientInitImgInfo // p: get_helprequest_and_toolname [for toolname] //-------------------------------------------------------------- VG_(debugLog)(1, "initimg", "Setup client env\n"); - env = setup_client_env(envp, toolname); + env = setup_client_env(iicii.envp, iicii.toolname); //-------------------------------------------------------------- // Setup client stack, eip, and VG_(client_arg[cv]) @@ -858,28 +852,28 @@ ClientInitImgInfo // p: fix_environment() [for 'env'] //-------------------------------------------------------------- { - void* init_sp = argv - 1; + void* init_sp = iicii.argv - 1; SizeT m1 = 1024 * 1024; SizeT m16 = 16 * m1; VG_(debugLog)(1, "initimg", "Setup client stack\n"); - clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur; - if (clstack_max_size < m1) clstack_max_size = m1; - if (clstack_max_size > m16) clstack_max_size = m16; - clstack_max_size = VG_PGROUNDUP(clstack_max_size); + iifii.clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur; + if (iifii.clstack_max_size < m1) iifii.clstack_max_size = m1; + if (iifii.clstack_max_size > m16) iifii.clstack_max_size = m16; + iifii.clstack_max_size = VG_PGROUNDUP(iifii.clstack_max_size); - ciii.initial_client_SP + iifii.initial_client_SP = setup_client_stack( init_sp, env, - &info, &ciii.client_auxv, - clstack_top, clstack_max_size ); + &info, &iifii.client_auxv, + iicii.clstack_top, iifii.clstack_max_size ); VG_(free)(env); VG_(debugLog)(2, "initimg", "Client info: " "initial_IP=%p initial_SP=%p initial_TOC=%p brk_base=%p\n", - (void*)(ciii.initial_client_IP), - (void*)(ciii.initial_client_SP), - (void*)(ciii.initial_client_TOC), + (void*)(iifii.initial_client_IP), + (void*)(iifii.initial_client_SP), + (void*)(iifii.initial_client_TOC), (void*)VG_(brk_base) ); } @@ -900,7 +894,7 @@ ClientInitImgInfo setup_client_dataseg( dseg_max_size ); } - return ciii; + return iifii; } @@ -908,15 +902,16 @@ ClientInitImgInfo /*=== TOP-LEVEL: VG_(finalise_thread1state) ===*/ /*====================================================================*/ -/* Make final adjustments to the initial image. Also, initialise the - VEX guest state for thread 1 (the root thread) and copy in - essential starting values. Is handed the ClientInitImgInfo created - by VG_(setup_client_initial_image). Upon return, the client's - memory and register state should be ready to start the JIT. */ -extern -void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, - ClientInitImgInfo ciii ) +/* Just before starting the client, we may need to make final + adjustments to its initial image. Also we need to set up the VEX + guest state for thread 1 (the root thread) and copy in essential + starting values. This is handed the IIFinaliseImageInfo created by + VG_(ii_create_image). +*/ +void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) { + ThreadArchState* arch = &VG_(threads)[1].arch; + /* On Linux we get client_{ip/sp/toc}, and start the client with all other registers zeroed. */ @@ -931,8 +926,8 @@ void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State)); /* Put essential stuff into the new state. */ - arch->vex.guest_ESP = ciii.initial_client_SP; - arch->vex.guest_EIP = ciii.initial_client_IP; + arch->vex.guest_ESP = iifii.initial_client_SP; + arch->vex.guest_EIP = iifii.initial_client_IP; /* initialise %cs, %ds and %ss to point at the operating systems default code, data and stack segments */ @@ -951,8 +946,8 @@ void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State)); /* Put essential stuff into the new state. */ - arch->vex.guest_RSP = ciii.initial_client_SP; - arch->vex.guest_RIP = ciii.initial_client_IP; + arch->vex.guest_RSP = iifii.initial_client_SP; + arch->vex.guest_RIP = iifii.initial_client_IP; # elif defined(VGP_ppc32_linux) vg_assert(0 == sizeof(VexGuestPPC32State) % 8); @@ -965,8 +960,8 @@ void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State)); /* Put essential stuff into the new state. */ - arch->vex.guest_GPR1 = ciii.initial_client_SP; - arch->vex.guest_CIA = ciii.initial_client_IP; + arch->vex.guest_GPR1 = iifii.initial_client_SP; + arch->vex.guest_CIA = iifii.initial_client_IP; # elif defined(VGP_ppc64_linux) vg_assert(0 == sizeof(VexGuestPPC64State) % 16); @@ -979,9 +974,9 @@ void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State)); /* Put essential stuff into the new state. */ - arch->vex.guest_GPR1 = ciii.initial_client_SP; - arch->vex.guest_GPR2 = ciii.initial_client_TOC; - arch->vex.guest_CIA = ciii.initial_client_IP; + arch->vex.guest_GPR1 = iifii.initial_client_SP; + arch->vex.guest_GPR2 = iifii.initial_client_TOC; + arch->vex.guest_CIA = iifii.initial_client_IP; # else # error Unknown platform diff --git a/coregrind/m_main.c b/coregrind/m_main.c index ad5c267e25..7aba9e68bc 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -1048,14 +1048,25 @@ void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total ) /*static*/ VgStack VG_(interim_stack); -/* This should get some address inside the stack on which we gained +/* These are the structures used to hold info for creating the initial + client image. + + 'iicii' mostly holds important register state present at system + startup (_start_valgrind). valgrind_main() then fills in the rest + of it and passes it to VG_(ii_create_image)(). That produces + 'iifii', which is later handed to VG_(ii_finalise_image). */ + +/* In all OS-instantiations, the_iicii has a field .sp_at_startup. + This should get some address inside the stack on which we gained control (eg, it could be the SP at startup). It doesn't matter exactly where in the stack it is. This value is passed to the - address space manager at startup, which uses it to identify the - initial stack segment and hence the upper end of the usable address - space. */ + address space manager at startup. On Linux, aspacem then uses it + to identify the initial stack segment and hence the upper end of + the usable address space. */ + +static IICreateImageInfo the_iicii; +static IIFinaliseImageInfo the_iifii; -static Addr sp_at_startup = 0; /* --- Forwards decls to do with shutdown --- */ @@ -1103,24 +1114,20 @@ static Addr* get_seg_starts ( /*OUT*/Int* n_acquired ) } +/* By the time we get to valgrind_main, the_iicii should already have + been filled in with any important details as required by whatever + OS we have been built for. +*/ 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 ) +Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) { HChar* toolname = "memcheck"; // default to Memcheck Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug - Addr clstack_top = 0; - SizeT clstack_max_size = 0; UInt* client_auxv = NULL; Int loglevel, i; Bool logging_to_fd; struct vki_rlimit zero = { 0, 0 }; - ClientInitImgInfo ciii; - VG_(memset)(&ciii, 0, sizeof(ClientInitImgInfo)); - //============================================================ // // Nb: startup is complex. Prerequisites are shown at every step. @@ -1236,7 +1243,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp, // p: logging //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Checking initial stack was noted\n"); - if (sp_at_startup == 0) { + if (the_iicii.sp_at_startup == 0) { VG_(debugLog)(0, "main", "Valgrind: FATAL: " "Initial stack was not noted.\n"); VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n"); @@ -1249,7 +1256,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp, // p: logging, plausible-stack //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Starting the address space manager\n"); - clstack_top = VG_(am_startup)( sp_at_startup ); + the_iicii.clstack_top = VG_(am_startup)( the_iicii.sp_at_startup ); VG_(debugLog)(1, "main", "Address space manager is running\n"); //-------------------------------------------------------------- @@ -1377,22 +1384,45 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp, // Setup client data (brk) segment. Initially a 1-page segment // which abuts a shrinkable reservation. // p: load_client() [for 'info' and hence VG_(brk_base)] + // + // p: _start_in_C (for zeroing out the_iicii and putting some + // initial values into it) //-------------------------------------------------------------- if (!need_help) { - VG_(debugLog)(1, "main", "Setting up initial image\n"); - ciii = VG_(setup_client_initial_image)( - argv, envp, toolname, - clstack_top, clstack_max_size - ); + VG_(debugLog)(1, "main", "Create initial image\n"); + +# if defined(VGO_linux) + the_iicii.argv = argv; + the_iicii.envp = envp; + the_iicii.toolname = toolname; +# elif defined(VGO_aix5) + /* the_iicii.intregs37 already set up */ + /* the_iicii.bootblock already set up */ + /* the_iicii.adler32_exp already set up */ + /* the_iicii.sp_at_startup is irrelevant */ + /* the_iicii.clstack_top is irrelevant */ + the_iicii.toolname = toolname; +# else +# error "Uknown platform" +# endif + + the_iifii = VG_(ii_create_image)( the_iicii ); + # if defined(VGO_aix5) - ciii.adler32_exp = ppc_aix_adler32_for_compressed_page; - ciii.compressed_page = VG_PGROUNDDN((Addr)ppc_aix_bootblock); - ciii.intregs37 = ppc_aix_initial_client_intregs37; - ciii.initial_client_SP = 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 ); + VG_(am_aix5_set_initial_client_sp)( the_iifii.initial_client_SP ); + /* Now have a look at said fake segment, so we can find out + the size of it. */ + { SizeT sz; + NSegment const* seg + = VG_(am_find_nsegment)( the_iifii.initial_client_SP ); + vg_assert(seg); + sz = seg->end - seg->start + 1; + vg_assert(sz >= 0 && sz <= 64*1024*1024); /* stay sane */ + the_iifii.clstack_max_size = sz; + } # endif } @@ -1678,11 +1708,11 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp, /* Also do the initial stack permissions. */ { NSegment const* seg - = VG_(am_find_nsegment)( ciii.initial_client_SP ); + = VG_(am_find_nsegment)( the_iifii.initial_client_SP ); vg_assert(seg); vg_assert(seg->kind == SkAnonC); - vg_assert(ciii.initial_client_SP >= seg->start); - vg_assert(ciii.initial_client_SP <= seg->end); + vg_assert(the_iifii.initial_client_SP >= seg->start); + vg_assert(the_iifii.initial_client_SP <= seg->end); # if defined(VGO_aix5) VG_(clstk_base) = seg->start; VG_(clstk_end) = seg->end; @@ -1693,14 +1723,15 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp, 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 >= seg->start); + vg_assert(the_iifii.initial_client_SP - VG_STACK_REDZONE_SZB + >= seg->start); VG_TRACK( die_mem_stack, seg->start, - ciii.initial_client_SP - VG_STACK_REDZONE_SZB - - seg->start ); + the_iifii.initial_client_SP - VG_STACK_REDZONE_SZB + - seg->start ); VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n", seg->start, - ciii.initial_client_SP-1 - VG_STACK_REDZONE_SZB); + the_iifii.initial_client_SP-1 - VG_STACK_REDZONE_SZB); } /* Also the assembly helpers. */ @@ -1720,23 +1751,22 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp, //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Initialise scheduler\n"); { NSegment const* seg - = VG_(am_find_nsegment)( ciii.initial_client_SP ); + = VG_(am_find_nsegment)( the_iifii.initial_client_SP ); vg_assert(seg); vg_assert(seg->kind == SkAnonC); - vg_assert(ciii.initial_client_SP >= seg->start); - vg_assert(ciii.initial_client_SP <= seg->end); - VG_(scheduler_init)( seg->end, clstack_max_size ); + vg_assert(the_iifii.initial_client_SP >= seg->start); + vg_assert(the_iifii.initial_client_SP <= seg->end); + VG_(scheduler_init)( seg->end, the_iifii.clstack_max_size ); } //-------------------------------------------------------------- // Set up state for the root thread // p: ? // setup_scheduler() [for sched-specific thread 1 stuff] - // VG_(setup_client_initial_image) - // [for 'ciii' initial layout info] + // VG_(ii_create_image) [for 'the_iicii' initial info] //-------------------------------------------------------------- - VG_(debugLog)(1, "main", "Finalise thread 1's state\n"); - VG_(finalise_thread1state)( &VG_(threads)[1].arch, ciii ); + VG_(debugLog)(1, "main", "Finalise initial image\n"); + VG_(ii_finalise_image)( the_iifii ); //-------------------------------------------------------------- // Initialise the pthread model @@ -2228,11 +2258,13 @@ void _start_in_C_linux ( UWord* pArgc ) Word argc = pArgc[0]; HChar** argv = (HChar**)&pArgc[1]; HChar** envp = (HChar**)&pArgc[1+argc+1]; - sp_at_startup = (Addr)pArgc; - r = valgrind_main( (Int)argc, argv, envp, - NULL/*aix5-specific stuff*/, - NULL/*aix5-specific stuff*/, - 0/*aix5-specific stuff*/ ); + + VG_(memset)( &the_iicii, 0, sizeof(the_iicii) ); + VG_(memset)( &the_iifii, 0, sizeof(the_iifii) ); + + the_iicii.sp_at_startup = (Addr)pArgc; + + r = valgrind_main( (Int)argc, argv, envp ); /* NOTREACHED */ VG_(exit)(r); } @@ -2293,7 +2325,18 @@ void _start_in_C_aix5 ( AIX5Bootblock* bootblock ) __NR_open = bootblock->__NR_open; __NR_read = bootblock->__NR_read; __NR_close = bootblock->__NR_close; + + VG_(memset)( &the_iicii, 0, sizeof(the_iicii) ); + VG_(memset)( &the_iifii, 0, sizeof(the_iifii) ); + intregs37 = &bootblock->iregs_pc_cr_lr_ctr_xer[0]; + the_iicii.intregs37 = intregs37; + the_iicii.bootblock = (void*)bootblock; + the_iicii.adler32_exp = bootblock->adler32; + + /* Not important on AIX. */ + the_iicii.sp_at_startup = (Addr)0x31415927ULL; + # if defined(VGP_ppc32_aix5) argc = (UWord)intregs37[3]; /* client's r3 == argc */ argv = (UWord)intregs37[4]; @@ -2303,11 +2346,9 @@ void _start_in_C_aix5 ( AIX5Bootblock* bootblock ) argv = (UWord)intregs37[15]; envp = (UWord)intregs37[16]; # endif - sp_at_startup = (Addr)0xDeadBeefDeadBeefULL; /* Not important on AIX. */ - r = valgrind_main( (Int)argc, (HChar**)argv, (HChar**)envp, - intregs37, - (void*)bootblock, - bootblock->adler32 ); + + r = valgrind_main( (Int)argc, (HChar**)argv, (HChar**)envp ); + /* NOTREACHED */ VG_(exit)(r); } diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index 9f76c6ed33..98a7e15b41 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -58,6 +58,7 @@ */ #include "pub_core_basics.h" +#include "pub_core_debuglog.h" #include "pub_core_vki.h" #include "pub_core_vkiscnums.h" // __NR_sched_yield #include "pub_core_threadstate.h" @@ -450,6 +451,9 @@ void VG_(scheduler_init) ( Addr clstack_end, SizeT clstack_size ) Int i; ThreadId tid_main; + VG_(debugLog)(1,"sched","sched_init: cls_end=0x%lx, cls_sz=%ld\n", + clstack_end, clstack_size); + vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1)); vg_assert(VG_IS_PAGE_ALIGNED(clstack_size)); diff --git a/coregrind/pub_core_initimg.h b/coregrind/pub_core_initimg.h index 933ceade79..a69220f016 100644 --- a/coregrind/pub_core_initimg.h +++ b/coregrind/pub_core_initimg.h @@ -32,6 +32,7 @@ #ifndef __PUB_CORE_INITIMG_H #define __PUB_CORE_INITIMG_H + //-------------------------------------------------------------------- // PURPOSE: Map the client executable into memory, then set up its // stack, environment and data section, ready for execution. Quite a @@ -39,17 +40,61 @@ // the AIX kernel does most of the work for us. //-------------------------------------------------------------------- +/* These are OS-specific and defined below. */ +typedef struct _IICreateImageInfo IICreateImageInfo; +typedef struct _IIFinaliseImageInfo IIFinaliseImageInfo; + +/* This is a two stage process. The first stage, which is most of the + work, creates the initial image in memory to the extent possible. + To do this it takes a bundle of information in an IICreateImageInfo + structure, which is gathered in an OS-specific way at startup. + This returns an IIFinaliseImageInfo structure: */ +extern +IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo ); + +/* Just before starting the client, we may need to make final + adjustments to its initial image. Also we need to set up the VEX + guest state for thread 1 (the root thread) and copy in essential + starting values. This is handed the IIFinaliseImageInfo created by + VG_(ii_create_image). */ +extern +void VG_(ii_finalise_image)( IIFinaliseImageInfo ); + + +/* Note that both IICreateImageInfo and IIFinaliseImageInfo are + OS-specific. We now go on to give instantiations of them + for supported OSes. */ + +/* ------------------------- Linux ------------------------- */ + #if defined(VGO_linux) -typedef - struct { - Addr initial_client_SP; - Addr initial_client_IP; - Addr initial_client_TOC; - UInt* client_auxv; - } - ClientInitImgInfo; + +struct _IICreateImageInfo { + /* ------ Mandatory fields ------ */ + HChar* toolname; + Addr sp_at_startup; + Addr clstack_top; + /* ------ Per-OS fields ------ */ + HChar** argv; + HChar** envp; +}; + +struct _IIFinaliseImageInfo { + /* ------ Mandatory fields ------ */ + SizeT clstack_max_size; + /* ------ Per-OS fields ------ */ + Addr initial_client_SP; + Addr initial_client_IP; + Addr initial_client_TOC; + UInt* client_auxv; +}; + + +/* ------------------------- AIX5 ------------------------- */ #elif defined(VGO_aix5) + +/* First we need to define this auxiliary structure. */ typedef struct { /* NOTE: VG_(ppc32/64_aix5_do_preloads_then_start_client) has @@ -85,52 +130,49 @@ typedef /* If the loading fails, we'll want to call a diagnostic function in C to figure out what happened. Here's it's function descriptor. Note, this runs on the simd cpu - (another nasty AIX kludge) */ + (a kludge, and will segfault in 64-bit mode). */ /* 112 */ void* p_diagnose_load_failure; } AIX5PreloadPage; -typedef - struct { - /* Pointer to the preload page. This is set up by - VG_(setup_client_initial_image). */ - AIX5PreloadPage* preloadpage; - /* Initial values for guest int registers (GPR0 .. GPR31, PC, - CR, LR, CTR, XER). Passed to us from the launcher. */ - ULong* intregs37; - /* Initial value for SP (which is merely a copy of r1's value, - intregs37[1]). */ - Addr initial_client_SP; - /* Address of the page compressed by the launcher. */ - Addr compressed_page; - /* Adler32 checksum of uncompressed data of said page. */ - UInt adler32_exp; - } - ClientInitImgInfo; +struct _IICreateImageInfo { + /* ------ Mandatory fields ------ */ + HChar* toolname; + Addr sp_at_startup; /* Not used on AIX. */ + Addr clstack_top; /* Not used on AIX. */ + /* ------ Per-OS fields ------ */ + /* Initial values for guest int registers (GPR0 .. GPR31, PC, CR, + LR, CTR, XER). Passed to us from the launcher. */ + ULong* intregs37; + /* AIX5Bootblock*, really */ + void* bootblock; + /* Adler32 checksum of uncompressed data of compressed page. */ + UInt adler32_exp; +}; + +struct _IIFinaliseImageInfo { + /* ------ Mandatory fields ------ */ + SizeT clstack_max_size; + /* ------ Per-OS fields ------ */ + /* Pointer to the preload page. The preload page and this pointer + to it are set up by VG_(ii_create_image). */ + AIX5PreloadPage* preloadpage; + /* Initial values for guest int registers (GPR0 .. GPR31, PC, + CR, LR, CTR, XER). Copied from the CII. */ + ULong* intregs37; + /* Initial value for SP (which is merely a copy of r1's value, + intregs37[1]). */ + Addr initial_client_SP; + /* Address of the page compressed by the launcher. */ + Addr compressed_page; + /* Adler32 checksum of uncompressed data of said page. */ + UInt adler32_exp; +}; #else -# error Unknown OS +# error "Unknown OS" #endif -/* Load the client, create the initial image (stack, etc), and - return a bundle of info in a ClientInitImgInfo. */ -extern ClientInitImgInfo - VG_(setup_client_initial_image)( - /*IN*/ HChar** argv, - /*IN*/ HChar** envp, - /*IN*/ HChar* toolname, - /*IN*/ Addr clstack_top, - /*IN*/ SizeT clstack_max_size - ); - -/* Make final adjustments to the initial image. Also, initialise the - VEX guest state for thread 1 (the root thread) and copy in - essential starting values. Is handed the ClientInitImgInfo created - by VG_(setup_client_initial_image). Upon return, the client's - memory and register state should be ready to start the JIT. */ -extern -void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch, - ClientInitImgInfo ciii ); #endif // __PUB_CORE_INITIMG_H -- 2.47.2