/* Processes a LC_UNIXTHREAD command. Returns 0 on success, -1 on any failure. The stack is mapped in and returned in *out_stack. The thread's entry point is returned in *out_entry. */ static int load_unixthread(vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, vki_uint8_t **out_entry, struct thread_command *threadcmd) { int err; vki_uint8_t *stack_end; int customstack; err = load_genericthread(&stack_end, &customstack, out_entry, threadcmd); if (err) return -1; if (!stack_end) { print("bad executable (no thread stack)\n"); return -1; } if (!customstack) { // Map the stack vki_size_t stacksize = VG_PGROUNDUP(default_stack_size()); vm_address_t stackbase = VG_PGROUNDDN(stack_end-stacksize); SysRes res; res = VG_(am_mmap_anon_fixed_client)(stackbase, stacksize, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC); check_mmap(res, stackbase, stacksize, "load_unixthread1"); if (out_stack_start) *out_stack_start = (vki_uint8_t *)stackbase; } else { // custom stack - mapped via __UNIXTHREAD segment } if (out_stack_end) *out_stack_end = stack_end; return 0; }
void test_VG_ROUND_et_al() { CHECK( 0 == VG_ROUNDDN(0, 1) ); CHECK( 1 == VG_ROUNDDN(1, 1) ); CHECK( 2 == VG_ROUNDDN(2, 1) ); CHECK( 3 == VG_ROUNDDN(3, 1) ); CHECK( 4 == VG_ROUNDDN(4, 1) ); CHECK( 5 == VG_ROUNDDN(5, 1) ); CHECK( 6 == VG_ROUNDDN(6, 1) ); CHECK( 7 == VG_ROUNDDN(7, 1) ); CHECK( 0 == VG_ROUNDUP(0, 1) ); CHECK( 1 == VG_ROUNDUP(1, 1) ); CHECK( 2 == VG_ROUNDUP(2, 1) ); CHECK( 3 == VG_ROUNDUP(3, 1) ); CHECK( 4 == VG_ROUNDUP(4, 1) ); CHECK( 5 == VG_ROUNDUP(5, 1) ); CHECK( 6 == VG_ROUNDUP(6, 1) ); CHECK( 7 == VG_ROUNDUP(7, 1) ); CHECK( 0 == VG_ROUNDDN(0, 2) ); CHECK( 0 == VG_ROUNDDN(1, 2) ); CHECK( 2 == VG_ROUNDDN(2, 2) ); CHECK( 2 == VG_ROUNDDN(3, 2) ); CHECK( 4 == VG_ROUNDDN(4, 2) ); CHECK( 4 == VG_ROUNDDN(5, 2) ); CHECK( 6 == VG_ROUNDDN(6, 2) ); CHECK( 6 == VG_ROUNDDN(7, 2) ); CHECK( 0 == VG_ROUNDUP(0, 2) ); CHECK( 2 == VG_ROUNDUP(1, 2) ); CHECK( 2 == VG_ROUNDUP(2, 2) ); CHECK( 4 == VG_ROUNDUP(3, 2) ); CHECK( 4 == VG_ROUNDUP(4, 2) ); CHECK( 6 == VG_ROUNDUP(5, 2) ); CHECK( 6 == VG_ROUNDUP(6, 2) ); CHECK( 8 == VG_ROUNDUP(7, 2) ); CHECK( 0 == VG_ROUNDDN(0, 4) ); CHECK( 0 == VG_ROUNDDN(1, 4) ); CHECK( 0 == VG_ROUNDDN(2, 4) ); CHECK( 0 == VG_ROUNDDN(3, 4) ); CHECK( 4 == VG_ROUNDDN(4, 4) ); CHECK( 4 == VG_ROUNDDN(5, 4) ); CHECK( 4 == VG_ROUNDDN(6, 4) ); CHECK( 4 == VG_ROUNDDN(7, 4) ); CHECK( 0 == VG_ROUNDUP(0, 4) ); CHECK( 4 == VG_ROUNDUP(1, 4) ); CHECK( 4 == VG_ROUNDUP(2, 4) ); CHECK( 4 == VG_ROUNDUP(3, 4) ); CHECK( 4 == VG_ROUNDUP(4, 4) ); CHECK( 8 == VG_ROUNDUP(5, 4) ); CHECK( 8 == VG_ROUNDUP(6, 4) ); CHECK( 8 == VG_ROUNDUP(7, 4) ); CHECK( 0 == VG_ROUNDDN(0, 8) ); CHECK( 0 == VG_ROUNDDN(1, 8) ); CHECK( 0 == VG_ROUNDDN(2, 8) ); CHECK( 0 == VG_ROUNDDN(3, 8) ); CHECK( 0 == VG_ROUNDDN(4, 8) ); CHECK( 0 == VG_ROUNDDN(5, 8) ); CHECK( 0 == VG_ROUNDDN(6, 8) ); CHECK( 0 == VG_ROUNDDN(7, 8) ); CHECK( 0 == VG_ROUNDUP(0, 8) ); CHECK( 8 == VG_ROUNDUP(1, 8) ); CHECK( 8 == VG_ROUNDUP(2, 8) ); CHECK( 8 == VG_ROUNDUP(3, 8) ); CHECK( 8 == VG_ROUNDUP(4, 8) ); CHECK( 8 == VG_ROUNDUP(5, 8) ); CHECK( 8 == VG_ROUNDUP(6, 8) ); CHECK( 8 == VG_ROUNDUP(7, 8) ); CHECK( 0 == VG_PGROUNDDN(0) ); CHECK( 0 == VG_PGROUNDDN(1) ); CHECK( 0 == VG_PGROUNDDN(2) ); CHECK( 0 == VG_PGROUNDDN(3) ); CHECK( 0 == VG_PGROUNDDN(4) ); CHECK( 0 == VG_PGROUNDDN(VKI_PAGE_SIZE-1) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDDN(VKI_PAGE_SIZE ) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDDN(VKI_PAGE_SIZE+1) ); CHECK( 0 == VG_PGROUNDUP(0) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(1) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(2) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(3) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(4) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(VKI_PAGE_SIZE-1) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(VKI_PAGE_SIZE ) ); CHECK( VKI_PAGE_SIZE*2 == VG_PGROUNDUP(VKI_PAGE_SIZE+1) ); }
IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii ) { /* Set up an AIX5PreloadPage structure with the names of $VALGRIND_LIB/PLATFORM/vgpreload_core.so $VALGRIND_LIB/PLATFORM/vgpreload_TOOL.so, if it exists xxx in "LD_PRELOAD=xxx", if it exists The client is started by running (on the simulator, of course) VG_(ppc{32,64}_aix5_do_preloads_then_start_client), which uses __loadx/_kload to load these .so's. When the preloading is done, various guest registers are restored to what they are really supposed to be at client startup, so these values too are stored in the AIX5PreloadPage. Finally, we jump to the client's entry point address. */ const HChar* _so = ".so"; const HChar* vgpreload_ = "vgpreload_"; const HChar* vgpreload_core_so = "vgpreload_core.so"; const HChar* errmsg_str = "valgrind: FATAL: core/tool/LD_PRELOAD= " "preload failed.\n"; Int plcore_len, pltool_len, ld_pre_len, errmsg_len; HChar *plcore_str, *pltool_str, *ld_pre_str; Bool have_tool_so, have_ld_pre; AIX5PreloadPage* pp; UChar* pc; Int szB, szPG; SysRes sres; IIFinaliseImageInfo iifii; VG_(memset)( &iifii, 0, sizeof(iifii) ); /* this can happen, if m_main decides to NULL it out */ if (VG_(args_the_exename) == NULL) VG_(err_missing_prog)(); vg_assert( iicii.toolname ); pltool_len = VG_(strlen)( VG_(libdir) ) + 1 /*slash*/ + VG_(strlen)(VG_PLATFORM) + 1 /*slash*/ + VG_(strlen)( vgpreload_ ) + VG_(strlen)( iicii.toolname ) + VG_(strlen)( _so ) + 1 /*NUL*/; vg_assert(pltool_len > 0); pltool_str = VG_(malloc)( pltool_len ); pltool_str[0] = 0; VG_(strcat)( pltool_str, VG_(libdir) ); VG_(strcat)( pltool_str, "/" ); VG_(strcat)( pltool_str, VG_PLATFORM ); VG_(strcat)( pltool_str, "/" ); VG_(strcat)( pltool_str, vgpreload_ ); 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 ); plcore_len = VG_(strlen)( VG_(libdir) ) + 1 /*slash*/ + VG_(strlen)(VG_PLATFORM) + 1 /*slash*/ + VG_(strlen)( vgpreload_core_so ) + 1 /*NUL*/; vg_assert(plcore_len > 0); plcore_str = VG_(malloc)( plcore_len ); plcore_str[0] = 0; VG_(strcat)( plcore_str, VG_(libdir) ); VG_(strcat)( plcore_str, "/" ); VG_(strcat)( plcore_str, VG_PLATFORM ); VG_(strcat)( plcore_str, "/" ); VG_(strcat)( plcore_str, vgpreload_core_so ); vg_assert( plcore_str[plcore_len-1] == 0 ); vg_assert( VG_(strlen)(plcore_str) == plcore_len-1 ); errmsg_len = VG_(strlen)( errmsg_str ) + 1 /*NUL*/; ld_pre_str = VG_(getenv)("LD_PRELOAD"); if (ld_pre_str && VG_(strlen)(ld_pre_str) > 0) { have_ld_pre = True; ld_pre_len = VG_(strlen)(ld_pre_str) + 1/*NUL*/; ld_pre_str = VG_(malloc)( ld_pre_len ); ld_pre_str[0] = 0; VG_(strcat)( ld_pre_str, VG_(getenv)("LD_PRELOAD") ); vg_assert( ld_pre_str[ld_pre_len-1] == 0); vg_assert( VG_(strlen)( ld_pre_str ) == ld_pre_len - 1 ); } else { have_ld_pre = False; ld_pre_len = 0; ld_pre_str = NULL; } VG_(debugLog)(1, "initimg", "plcore_str = '%s'\n", plcore_str ); VG_(debugLog)(1, "initimg", "pltool_str = '%s'\n", pltool_str ); VG_(debugLog)(1, "initimg", "ld_pre_str = '%s'\n", ld_pre_str ); if (0 != VG_(access)(plcore_str, True,False,True)) VG_(err_config_error)("Can't find core preload " "(vgpreload_core.so)"); have_tool_so = 0 == VG_(access)(pltool_str, True,False,True); /* Figure out how much space is needed for an AIX5PreloadInfo followed by the three preload strings. */ vg_assert((sizeof(AIX5PreloadPage) % 4) == 0); /* paranoia */ szB = sizeof(AIX5PreloadPage) + plcore_len + (have_tool_so ? pltool_len : 0) + (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_assert(szB > 0); vg_assert(szB < szPG * VKI_PAGE_SIZE); /* We'll need szPG pages of anonymous, rw-, client space (needs w so we can write it here) */ sres = VG_(am_mmap_anon_float_client) ( szPG * VKI_PAGE_SIZE, VKI_PROT_READ|VKI_PROT_WRITE); if (sres.isError) VG_(err_config_error)("Can't allocate client page(s) " "for preload info"); pp = (AIX5PreloadPage*)sres.res; VG_(debugLog)(2, "initimg", "preload page allocation succeeded at %p\n", pp); /* Zero out the initial structure. */ VG_(memset)(pp, 0, sizeof(AIX5PreloadPage)); pc = (UChar*)pp; pc += sizeof(AIX5PreloadPage); VG_(memcpy)(pc, plcore_str, plcore_len); pp->off_preloadcorename = pc - (UChar*)pp; pc += plcore_len; if (have_tool_so) { VG_(memcpy)(pc, pltool_str, pltool_len); pp->off_preloadtoolname = pc - (UChar*)pp; pc += pltool_len; } if (have_ld_pre) { VG_(memcpy)(pc, ld_pre_str, ld_pre_len); pp->off_ld_preloadname = pc - (UChar*)pp; pc += ld_pre_len; } VG_(memcpy)(pc, errmsg_str, errmsg_len); pp->off_errmsg = pc - (UChar*)pp; pp->len_errmsg = errmsg_len - 1; /* -1: skip terminating NUL */ vg_assert(pc <= ((UChar*)pp) - 1 + szPG * VKI_PAGE_SIZE); VG_(free)(plcore_str); VG_(free)(pltool_str); /* Fill in all the other preload page fields that we can right now. */ # if defined(VGP_ppc32_aix5) vg_assert(__NR_AIX5___loadx != __NR_AIX5_UNKNOWN); pp->nr_load = __NR_AIX5___loadx; # else /* defined(VGP_ppc64_aix5) */ vg_assert(__NR_AIX5_kload != __NR_AIX5_UNKNOWN); pp->nr_load = __NR_AIX5_kload; # endif vg_assert(__NR_AIX5_kwrite != __NR_AIX5_UNKNOWN); pp->nr_kwrite = __NR_AIX5_kwrite; /* kwrite */ vg_assert(__NR_AIX5__exit != __NR_AIX5_UNKNOWN); pp->nr__exit = __NR_AIX5__exit; /* _exit */ pp->p_diagnose_load_failure = &diagnose_load_failure; 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; }
static void main2(void) { int err, padfile; struct exeinfo info; extern char _end; int *esp; char buf[strlen(valgrind_lib) + sizeof(stage2) + 16]; info.exe_end = VG_PGROUNDDN(init_sp); // rounding down info.exe_base = KICKSTART_BASE; printf("info.exe_end = %p\n", info.exe_end); #ifdef HAVE_PIE info.exe_base = VG_ROUNDDN(info.exe_end - 0x02000000, 0x10000000); assert(info.exe_base >= VG_PGROUNDUP(&_end)); info.map_base = info.exe_base + 0x01000000 ; #else // If this system doesn't have PIE (position-independent executables), // we have to choose a hardwired location for stage2. // info.exe_base = VG_PGROUNDUP(&_end); printf("info.exe_base = %p\n", info.exe_base); info.map_base = KICKSTART_BASE + 0x01000000 ; printf("info.map_base = %p\n", info.map_base); #endif info.argv = NULL; snprintf(buf, sizeof(buf), "%s/%s", valgrind_lib, stage2); printf("valgrind_lib = %s\n",valgrind_lib); err = do_exec(buf, &info); if (err != 0) { fprintf(stderr, "valgrind: failed to load %s: %s\n", buf, strerror(err)); exit(1); } /* Make sure stage2's dynamic linker can't tromp on the lower part of the address space. */ padfile = as_openpadfile(); as_pad(0, (void *)info.map_base, padfile); // map base is the start of our stuff printf("init sp : %x\n", init_sp); esp = fix_auxv(init_sp, &info, padfile); printf("after fix_auxb\n"); if (1) { printf("---------- launch stage 2 ----------\n"); printf("eip=%p esp=%p\n", (void *)info.init_eip, esp); foreach_map(prmap, /*dummy*/NULL); } VG_(debugLog)(1, "stage1", "main2(): starting stage2\n"); printf("jumping to stage 2 \n"); printf("esp : %x \n eip : %x\n",esp, info.init_eip); jump_and_switch_stacks( (Addr) esp, /* stack */ (Addr) info.init_eip /* Where to jump */ ); /*NOTREACHED*/ assert(0); }