예제 #1
0
파일: macho.c 프로젝트: mikaeleiman/rmalloc
/* 
   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;
}
예제 #2
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) );
}
예제 #3
0
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;
}
예제 #4
0
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);
}