Home | History | Annotate | Download | only in m_initimg
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Startup: create initial process image on AIX5                ---*/
      4 /*---                                               initimg-aix5.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2006-2010 OpenWorks LLP
     12       info (at) open-works.co.uk
     13 
     14    This program is free software; you can redistribute it and/or
     15    modify it under the terms of the GNU General Public License as
     16    published by the Free Software Foundation; either version 2 of the
     17    License, or (at your option) any later version.
     18 
     19    This program is distributed in the hope that it will be useful, but
     20    WITHOUT ANY WARRANTY; without even the implied warranty of
     21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22    General Public License for more details.
     23 
     24    You should have received a copy of the GNU General Public License
     25    along with this program; if not, write to the Free Software
     26    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     27    02111-1307, USA.
     28 
     29    The GNU General Public License is contained in the file COPYING.
     30 
     31    Neither the names of the U.S. Department of Energy nor the
     32    University of California nor the names of its contributors may be
     33    used to endorse or promote products derived from this software
     34    without prior written permission.
     35 */
     36 
     37 #if defined(VGO_aix5)
     38 
     39 #include "pub_core_basics.h"
     40 #include "pub_core_vki.h"
     41 #include "pub_core_vkiscnums.h"
     42 #include "pub_core_debuglog.h"
     43 #include "pub_core_libcbase.h"
     44 #include "pub_core_libcassert.h"
     45 #include "pub_core_libcfile.h"
     46 #include "pub_core_libcproc.h"
     47 #include "pub_core_libcprint.h"
     48 #include "pub_core_xarray.h"
     49 #include "pub_core_clientstate.h"
     50 #include "pub_core_aspacemgr.h"
     51 #include "pub_core_mallocfree.h"
     52 #include "pub_core_machine.h"
     53 #include "pub_core_ume.h"
     54 #include "pub_core_options.h"
     55 #include "pub_core_threadstate.h"     /* ThreadArchState */
     56 #include "pub_core_tooliface.h"       /* VG_TRACK */
     57 #include "pub_core_trampoline.h" /* VG_(ppc32_aix5_do_preloads_then_start_client) */
     58 #include "pub_core_syscall.h"         // VG_(do_syscall1)
     59 #include "pub_core_initimg.h"         /* self */
     60 
     61 #include "simple_huffman.c"
     62 
     63 #if !defined(VGP_ppc32_aix5) && !defined(VGP_ppc64_aix5)
     64 #error "This should only be compiled on AIX"
     65 #endif
     66 
     67 
     68 static void diagnose_load_failure ( void );
     69 
     70 /* --- Create the client's initial memory image. --- */
     71 
     72 IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii )
     73 {
     74    /* Set up an AIX5PreloadPage structure with the names of
     75 
     76          $VALGRIND_LIB/vgpreload_core_PLATFORM.so
     77          $VALGRIND_LIB/vgpreload_TOOL_PLATFORM.so, if it exists
     78          xxx in "LD_PRELOAD=xxx", if it exists
     79 
     80       The client is started by running (on the simulator, of course)
     81       VG_(ppc{32,64}_aix5_do_preloads_then_start_client), which uses
     82       __loadx/_kload to load these .so's.  When the preloading is
     83       done, various guest registers are restored to what they are
     84       really supposed to be at client startup, so these values too are
     85       stored in the AIX5PreloadPage.  Finally, we jump to the client's
     86       entry point address.
     87    */
     88    const HChar* _so        = ".so";
     89    const HChar* vgpreload_ = "vgpreload_";
     90    const HChar* core       = "core";
     91    const HChar* errmsg_str
     92                    = "valgrind: FATAL: core/tool/LD_PRELOAD= "
     93                      "preload failed.\n";
     94    Int    plcore_len,  pltool_len, ld_pre_len, errmsg_len;
     95    HChar *plcore_str, *pltool_str, *ld_pre_str;
     96    Bool   have_tool_so, have_ld_pre;
     97 
     98    AIX5PreloadPage* pp;
     99    UChar*           pc;
    100    Int              szB, szPG;
    101    SysRes           sres;
    102 
    103    IIFinaliseImageInfo iifii;
    104    VG_(memset)( &iifii, 0, sizeof(iifii) );
    105 
    106    /* this can happen, if m_main decides to NULL it out */
    107    if (VG_(args_the_exename) == NULL)
    108       VG_(err_missing_prog)();
    109 
    110    vg_assert( iicii.toolname );
    111    pltool_len = VG_(strlen)( VG_(libdir) )
    112                 + 1 /*slash*/
    113                 + VG_(strlen)( vgpreload_ )
    114                 + VG_(strlen)( iicii.toolname )
    115                 + 1 /*dash*/
    116                 + VG_(strlen)(VG_PLATFORM)
    117                 + VG_(strlen)( _so )
    118                 + 1 /*NUL*/;
    119    vg_assert(pltool_len > 0);
    120    pltool_str = VG_(malloc)( "initimg-aix5.ici.1", pltool_len );
    121    pltool_str[0] = 0;
    122    VG_(strcat)( pltool_str, VG_(libdir) );
    123    VG_(strcat)( pltool_str, "/" );
    124    VG_(strcat)( pltool_str, vgpreload_ );
    125    VG_(strcat)( pltool_str, iicii.toolname );
    126    VG_(strcat)( pltool_str, "-" );
    127    VG_(strcat)( pltool_str, VG_PLATFORM );
    128    VG_(strcat)( pltool_str, _so );
    129    vg_assert( pltool_str[pltool_len-1] == 0);
    130    vg_assert( VG_(strlen)(pltool_str) == pltool_len-1 );
    131 
    132    plcore_len = VG_(strlen)( VG_(libdir) )
    133                 + 1 /*slash*/
    134                 + VG_(strlen)( vgpreload_ )
    135                 + VG_(strlen)( core )
    136                 + 1 /*dash*/
    137                 + VG_(strlen)(VG_PLATFORM)
    138                 + VG_(strlen)(_so)
    139                 + 1 /*NUL*/;
    140    vg_assert(plcore_len > 0);
    141    plcore_str = VG_(malloc)( "initimg-aix5.ici.2", plcore_len );
    142    plcore_str[0] = 0;
    143    VG_(strcat)( plcore_str, VG_(libdir) );
    144    VG_(strcat)( plcore_str, "/" );
    145    VG_(strcat)( plcore_str, vgpreload_ );
    146    VG_(strcat)( plcore_str, core );
    147    VG_(strcat)( plcore_str, "-" );
    148    VG_(strcat)( plcore_str, VG_PLATFORM );
    149    VG_(strcat)( plcore_str, _so );
    150    vg_assert( plcore_str[plcore_len-1] == 0 );
    151    vg_assert( VG_(strlen)(plcore_str) == plcore_len-1 );
    152 
    153    errmsg_len = VG_(strlen)( errmsg_str )
    154                 + 1 /*NUL*/;
    155 
    156    ld_pre_str = VG_(getenv)("LD_PRELOAD");
    157    if (ld_pre_str && VG_(strlen)(ld_pre_str) > 0) {
    158       have_ld_pre = True;
    159       ld_pre_len  = VG_(strlen)(ld_pre_str) + 1/*NUL*/;
    160       ld_pre_str = VG_(malloc)( "initimg-aix5.ici.3", ld_pre_len );
    161       ld_pre_str[0] = 0;
    162       VG_(strcat)( ld_pre_str, VG_(getenv)("LD_PRELOAD") );
    163       vg_assert( ld_pre_str[ld_pre_len-1] == 0);
    164       vg_assert( VG_(strlen)( ld_pre_str ) == ld_pre_len - 1 );
    165    } else {
    166       have_ld_pre = False;
    167       ld_pre_len  = 0;
    168       ld_pre_str  = NULL;
    169    }
    170 
    171    VG_(debugLog)(1, "initimg", "plcore_str = '%s'\n", plcore_str );
    172    VG_(debugLog)(1, "initimg", "pltool_str = '%s'\n", pltool_str );
    173    VG_(debugLog)(1, "initimg", "ld_pre_str = '%s'\n", ld_pre_str );
    174 
    175    if (0 != VG_(access)(plcore_str, True,False,True))
    176       VG_(err_config_error)("Can't find core preload "
    177                             "(vgpreload_core-<platform>.so)");
    178 
    179    have_tool_so = 0 == VG_(access)(pltool_str, True,False,True);
    180 
    181    /* Figure out how much space is needed for an AIX5PreloadInfo
    182       followed by the three preload strings. */
    183 
    184    vg_assert((sizeof(AIX5PreloadPage) % 4) == 0); /* paranoia */
    185 
    186    szB = sizeof(AIX5PreloadPage) + plcore_len
    187                                  + (have_tool_so ? pltool_len : 0)
    188                                  + (have_ld_pre ? ld_pre_len : 0)
    189                                  + errmsg_len;
    190    szPG = VG_PGROUNDUP(szB+1) / VKI_PAGE_SIZE;
    191    VG_(debugLog)(2, "initimg",
    192                     "preload page size: %d bytes, %d pages\n", szB, szPG);
    193 
    194    vg_assert(szB > 0);
    195    vg_assert(szB < szPG * VKI_PAGE_SIZE);
    196 
    197    /* We'll need szPG pages of anonymous, rw-, client space (needs w
    198       so we can write it here) */
    199    sres = VG_(am_mmap_anon_float_client)
    200              ( szPG * VKI_PAGE_SIZE, VKI_PROT_READ|VKI_PROT_WRITE);
    201    if (sres.isError)
    202       VG_(err_config_error)("Can't allocate client page(s) "
    203                             "for preload info");
    204    pp = (AIX5PreloadPage*)sres.res;
    205 
    206    VG_(debugLog)(2, "initimg", "preload page allocation succeeded at %p\n", pp);
    207 
    208    /* Zero out the initial structure. */
    209    VG_(memset)(pp, 0, sizeof(AIX5PreloadPage));
    210 
    211    pc = (UChar*)pp;
    212    pc += sizeof(AIX5PreloadPage);
    213    VG_(memcpy)(pc, plcore_str, plcore_len);
    214    pp->off_preloadcorename = pc - (UChar*)pp;
    215    pc += plcore_len;
    216    if (have_tool_so) {
    217       VG_(memcpy)(pc, pltool_str, pltool_len);
    218       pp->off_preloadtoolname = pc - (UChar*)pp;
    219       pc += pltool_len;
    220    }
    221    if (have_ld_pre) {
    222       VG_(memcpy)(pc, ld_pre_str, ld_pre_len);
    223       pp->off_ld_preloadname = pc - (UChar*)pp;
    224       pc += ld_pre_len;
    225    }
    226    VG_(memcpy)(pc, errmsg_str, errmsg_len);
    227    pp->off_errmsg = pc - (UChar*)pp;
    228    pp->len_errmsg = errmsg_len - 1; /* -1: skip terminating NUL */
    229 
    230    vg_assert(pc <= ((UChar*)pp) - 1 + szPG * VKI_PAGE_SIZE);
    231 
    232    VG_(free)(plcore_str);
    233    VG_(free)(pltool_str);
    234 
    235    /* Fill in all the other preload page fields that we can right
    236       now. */
    237 #  if defined(VGP_ppc32_aix5)
    238    vg_assert(__NR_AIX5___loadx != __NR_AIX5_UNKNOWN);
    239    pp->nr_load = __NR_AIX5___loadx;
    240 #  else /* defined(VGP_ppc64_aix5) */
    241    vg_assert(__NR_AIX5_kload != __NR_AIX5_UNKNOWN);
    242    pp->nr_load = __NR_AIX5_kload;
    243 #  endif
    244 
    245    vg_assert(__NR_AIX5_kwrite  != __NR_AIX5_UNKNOWN);
    246    pp->nr_kwrite = __NR_AIX5_kwrite;   /* kwrite */
    247 
    248    vg_assert(__NR_AIX5__exit   != __NR_AIX5_UNKNOWN);
    249    pp->nr__exit = __NR_AIX5__exit;    /* _exit */
    250 
    251    pp->p_diagnose_load_failure = &diagnose_load_failure;
    252 
    253    iifii.preloadpage       = pp;
    254    iifii.intregs37         = iicii.intregs37;
    255    iifii.initial_client_SP = iicii.intregs37[1]; /* r1 */
    256    iifii.compressed_page   = VG_PGROUNDDN((Addr)iicii.bootblock);
    257    iifii.adler32_exp       = iicii.adler32_exp;
    258    iifii.clstack_max_size  = 0; /* we don't know yet */
    259    return iifii;
    260 }
    261 
    262 
    263 /* --- Finalise the initial image and register state. --- */
    264 
    265 static UChar unz_page[VKI_PAGE_SIZE];
    266 
    267 static UInt compute_adler32 ( void* addr, UWord len )
    268 {
    269    UInt   s1 = 1;
    270    UInt   s2 = 0;
    271    UChar* buf = (UChar*)addr;
    272    while (len > 0) {
    273       s1 += buf[0];
    274       s2 += s1;
    275       s1 %= 65521;
    276       s2 %= 65521;
    277       len--;
    278       buf++;
    279    }
    280    return (s2 << 16) + s1;
    281 }
    282 
    283 /* Just before starting the client, we may need to make final
    284    adjustments to its initial image.  Also we need to set up the VEX
    285    guest state for thread 1 (the root thread) and copy in essential
    286    starting values.  This is handed the IIFinaliseImageInfo created by
    287    VG_(ii_create_image).
    288 */
    289 void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
    290 {
    291    UInt   adler32_act;
    292    SysRes sres;
    293    /* On AIX we get a block of 37 words telling us the initial state
    294       for (GPR0 .. GPR31, PC, CR, LR, CTR, XER), and we start with all
    295       the other registers zeroed. */
    296 
    297    ThreadArchState* arch = &VG_(threads)[1].arch;
    298 
    299 #  if defined(VGP_ppc32_aix5)
    300 
    301    vg_assert(0 == sizeof(VexGuestPPC32State) % 16);
    302 
    303    /* Zero out the initial state, and set up the simulated FPU in a
    304       sane way. */
    305    LibVEX_GuestPPC32_initialise(&arch->vex);
    306 
    307    /* Zero out the shadow areas. */
    308    VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestPPC32State));
    309    VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestPPC32State));
    310 
    311 #  else /* defined(VGP_ppc64_aix5) */
    312 
    313    vg_assert(0 == sizeof(VexGuestPPC64State) % 16);
    314 
    315    /* Zero out the initial state, and set up the simulated FPU in a
    316       sane way. */
    317    LibVEX_GuestPPC64_initialise(&arch->vex);
    318 
    319    /* Zero out the shadow areas. */
    320    VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestPPC64State));
    321    VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestPPC64State));
    322 
    323 #  endif
    324 
    325    /* iifii.intregs37 contains the integer register state as it needs
    326       to be at client startup.  These values are supplied by the
    327       launcher.  The 37 regs are:initial values from launcher for:
    328       GPR0 .. GPR31, PC, CR, LR, CTR, XER. */
    329 
    330    /* Put essential stuff into the new state. */
    331    arch->vex.guest_GPR0  =  (UWord)iifii.intregs37[0];
    332    arch->vex.guest_GPR1  =  (UWord)iifii.intregs37[1];
    333    arch->vex.guest_GPR2  =  (UWord)iifii.intregs37[2];
    334    arch->vex.guest_GPR3  =  (UWord)iifii.intregs37[3];
    335    arch->vex.guest_GPR4  =  (UWord)iifii.intregs37[4];
    336    arch->vex.guest_GPR5  =  (UWord)iifii.intregs37[5];
    337    arch->vex.guest_GPR6  =  (UWord)iifii.intregs37[6];
    338    arch->vex.guest_GPR7  =  (UWord)iifii.intregs37[7];
    339    arch->vex.guest_GPR8  =  (UWord)iifii.intregs37[8];
    340    arch->vex.guest_GPR9  =  (UWord)iifii.intregs37[9];
    341    arch->vex.guest_GPR10 =  (UWord)iifii.intregs37[10];
    342    arch->vex.guest_GPR11 =  (UWord)iifii.intregs37[11];
    343    arch->vex.guest_GPR12 =  (UWord)iifii.intregs37[12];
    344    arch->vex.guest_GPR13 =  (UWord)iifii.intregs37[13];
    345    arch->vex.guest_GPR14 =  (UWord)iifii.intregs37[14];
    346    arch->vex.guest_GPR15 =  (UWord)iifii.intregs37[15];
    347    arch->vex.guest_GPR16 =  (UWord)iifii.intregs37[16];
    348    arch->vex.guest_GPR17 =  (UWord)iifii.intregs37[17];
    349    arch->vex.guest_GPR18 =  (UWord)iifii.intregs37[18];
    350    arch->vex.guest_GPR19 =  (UWord)iifii.intregs37[19];
    351    arch->vex.guest_GPR20 =  (UWord)iifii.intregs37[20];
    352    arch->vex.guest_GPR21 =  (UWord)iifii.intregs37[21];
    353    arch->vex.guest_GPR22 =  (UWord)iifii.intregs37[22];
    354    arch->vex.guest_GPR23 =  (UWord)iifii.intregs37[23];
    355    arch->vex.guest_GPR24 =  (UWord)iifii.intregs37[24];
    356    arch->vex.guest_GPR25 =  (UWord)iifii.intregs37[25];
    357    arch->vex.guest_GPR26 =  (UWord)iifii.intregs37[26];
    358    arch->vex.guest_GPR27 =  (UWord)iifii.intregs37[27];
    359    arch->vex.guest_GPR28 =  (UWord)iifii.intregs37[28];
    360    arch->vex.guest_GPR29 =  (UWord)iifii.intregs37[29];
    361    arch->vex.guest_GPR30 =  (UWord)iifii.intregs37[30];
    362    arch->vex.guest_GPR31 =  (UWord)iifii.intregs37[31];
    363 
    364    arch->vex.guest_CIA      = (UWord)iifii.intregs37[32+0];
    365    arch->vex.guest_LR       = (UWord)iifii.intregs37[32+2];
    366    arch->vex.guest_CTR      = (UWord)iifii.intregs37[32+3];
    367 
    368 #  if defined(VGP_ppc32_aix5)
    369 
    370    LibVEX_GuestPPC32_put_CR(  (UWord)iifii.intregs37[32+1], &arch->vex );
    371    LibVEX_GuestPPC32_put_XER( (UWord)iifii.intregs37[32+4], &arch->vex );
    372 
    373    /* Set the cache line size (KLUDGE) */
    374    VG_(machine_ppc32_set_clszB)( 128 );
    375 
    376 #  else /* defined(VGP_ppc64_aix5) */
    377 
    378    LibVEX_GuestPPC64_put_CR(  (UWord)iifii.intregs37[32+1], &arch->vex );
    379    LibVEX_GuestPPC64_put_XER( (UWord)iifii.intregs37[32+4], &arch->vex );
    380 
    381    /* Set the cache line size (KLUDGE) */
    382    VG_(machine_ppc64_set_clszB)( 128 );
    383 
    384 #  endif
    385 
    386    /* Fix up the client's command line.  Its argc/v/envp is in r3/4/5
    387       (32-bit AIX) or r14/15/16 (64-bit AIX).  but that is for the
    388       Valgrind invokation as a whole.  Hence we need to decrement argc
    389       and advance argv to step over the args for Valgrind, and the
    390       name of the Valgrind tool exe bogusly inserted by the launcher
    391       (hence the "+1"). */
    392 
    393 #  if defined(VGP_ppc32_aix5)
    394 
    395    { UWord n_vargs = VG_(sizeXA)( VG_(args_for_valgrind) );
    396      vg_assert(arch->vex.guest_GPR3 >= 1 + n_vargs);
    397      arch->vex.guest_GPR3 -= (1 + n_vargs);
    398      arch->vex.guest_GPR4 += sizeof(UWord) * (1 + n_vargs);
    399    }
    400 
    401 #  else /* defined(VGP_ppc64_aix5) */
    402 
    403    { UWord n_vargs = VG_(sizeXA)( VG_(args_for_valgrind) );
    404      vg_assert(arch->vex.guest_GPR14 >= 1 + n_vargs);
    405      arch->vex.guest_GPR14 -= (1 + n_vargs);
    406      arch->vex.guest_GPR15 += sizeof(UWord) * (1 + n_vargs);
    407    }
    408 
    409 #  endif
    410 
    411    /* At this point the guest register state is correct for client
    412       startup.  However, that's not where we want to start; in fact we
    413       want to start at VG_(ppc{32,64}_aix5_do_preloads_then_start_client),
    414       passing it iifii.preloadpage in r3.  This will load the core/tool
    415       preload .so's, then restore r2-r10 from what's stashed in the
    416       preloadpage, and then start the client really.  Hence: */
    417 
    418    /* Save r2-r10 and the client start point in preloadpage */
    419    iifii.preloadpage->r2  = (ULong)arch->vex.guest_GPR2;
    420    iifii.preloadpage->r3  = (ULong)arch->vex.guest_GPR3;
    421    iifii.preloadpage->r4  = (ULong)arch->vex.guest_GPR4;
    422    iifii.preloadpage->r5  = (ULong)arch->vex.guest_GPR5;
    423    iifii.preloadpage->r6  = (ULong)arch->vex.guest_GPR6;
    424    iifii.preloadpage->r7  = (ULong)arch->vex.guest_GPR7;
    425    iifii.preloadpage->r8  = (ULong)arch->vex.guest_GPR8;
    426    iifii.preloadpage->r9  = (ULong)arch->vex.guest_GPR9;
    427    iifii.preloadpage->r10 = (ULong)arch->vex.guest_GPR10;
    428    iifii.preloadpage->client_start = (ULong)arch->vex.guest_CIA;
    429 
    430 
    431 #  if defined(VGP_ppc32_aix5)
    432 
    433    /* Set up to start at VG_(ppc32_aix5_do_preloads_then_start_client) */
    434    arch->vex.guest_CIA = (UWord)&VG_(ppc32_aix5_do_preloads_then_start_client);
    435 
    436 #  else /* defined(VGP_ppc64_aix5) */
    437 
    438    /* Set up to start at VG_(ppc64_aix5_do_preloads_then_start_client) */
    439    arch->vex.guest_CIA = (UWord)&VG_(ppc64_aix5_do_preloads_then_start_client);
    440 
    441 #  endif
    442 
    443    arch->vex.guest_GPR3 = (UWord)iifii.preloadpage;
    444 
    445    /* The rest of the preloadpage fields will already have been filled
    446       in by VG_(setup_client_initial_image).  So we're done. */
    447 
    448    /* Finally, decompress the page compressed by the launcher.  We
    449       can't do this any earlier, because the page is (effectively)
    450       decompressed in place, which trashes iifii.intregs37.  So we have
    451       to wait till this point, at which we're done with iifii.intregs37
    452       (to be precise, with what it points at). */
    453    VG_(debugLog)(1, "initimg", "decompressing page at %p\n",
    454                     (void*)iifii.compressed_page);
    455    vg_assert(VG_IS_PAGE_ALIGNED(iifii.compressed_page));
    456 
    457    Huffman_Uncompress( (void*)iifii.compressed_page, unz_page,
    458                        VKI_PAGE_SIZE, VKI_PAGE_SIZE );
    459    adler32_act = compute_adler32(unz_page, VKI_PAGE_SIZE);
    460 
    461    VG_(debugLog)(1, "initimg",
    462                     "decompress done, adler32s: act 0x%x, exp 0x%x\n",
    463                     adler32_act, iifii.adler32_exp );
    464 
    465    VG_(memcpy)((void*)iifii.compressed_page, unz_page, VKI_PAGE_SIZE);
    466 
    467    VG_(debugLog)(1, "initimg", "copy back done\n");
    468 
    469    /* Tell the tool that we just wrote to the registers. */
    470    VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
    471              sizeof(VexGuestArchState));
    472 
    473    /* Determine the brk limit. */
    474    VG_(debugLog)(1, "initimg", "establishing current brk ..\n");
    475    vg_assert(__NR_AIX5_sbrk != __NR_AIX5_UNKNOWN);
    476    sres = VG_(do_syscall1)(__NR_AIX5_sbrk, 0);
    477    vg_assert(sres.err == 0); /* assert no error */
    478    VG_(brk_base) = VG_(brk_limit) = sres.res;
    479    VG_(debugLog)(1, "initimg", ".. brk = %p\n", (void*)VG_(brk_base));
    480 }
    481 
    482 
    483 /* --- Diagnose preload failures. --- */
    484 
    485 /* This is a nasty but effective kludge.  The address of the following
    486    function is put into the preload page.  So, if a preload failure
    487    happens, we call here to get helpful info printed out (the call
    488    site is in m_trampoline.S).  This is a dirty hack (1) because
    489    diagnose_load_failure runs on the simulated CPU, not the real one
    490    and (2) because it induces a libc dependency.  Oh well. */
    491 
    492 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
    493 #include <stdlib.h>
    494 #include <sys/ldr.h>
    495 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
    496 
    497 static void diagnose_load_failure ( void )
    498 {
    499 #  define NBUF 1024
    500    UChar buf[NBUF];
    501    VG_(debugLog)(0, "initimg", "Diagnosing load failure\n");
    502    if (sizeof(void*) == 8) {
    503       VG_(debugLog)(0, "initimg", "Can't safely do loadquery() "
    504                                   "in 64-bit mode.  Sorry.\n");
    505       /* because this requires dynamic linking to be working (IIRC)
    506          and it isn't; the tool file's dynamic linking was never done,
    507          because it was loaded by the bootstrap stub, which simply did
    508          sys_kload() but didn't make usla do the relevant
    509          relocations. */
    510    } else {
    511       UChar** p;
    512       Int r = loadquery(L_GETMESSAGES, buf, NBUF);
    513       VG_(debugLog)(0, "initimg", "loadquery returned %d (0 = success)\n", r);
    514       p = (UChar**)(&buf[0]);
    515       for (; *p; p++)
    516          VG_(debugLog)(0, "initimg", "\"%s\"\n", *p);
    517       VG_(debugLog)(0, "initimg", "Use /usr/sbin/execerror to make "
    518                                   "sense of above string(s)\n");
    519       VG_(debugLog)(0, "initimg", "See also comments at the bottom of\n");
    520       VG_(debugLog)(0, "initimg", "coregrind/m_initimg/"
    521                                   "initimg-aix5.c (in Valgrind sources)\n");
    522    }
    523 #  undef NBUF
    524 }
    525 
    526 /* Take the strings that this prints out and feed them
    527    to /usr/sbin/execerror.  For example, it might print
    528 
    529      (ld 3 1 __libc_freeres /foo/bar/vgpreload_core-ppc32-aix5.so
    530 
    531    in which case
    532 
    533      $ execerror xyzzy \
    534           "(ld 3 1 __libc_freeres /foo/bar/vgpreload_core-ppc32-aix5.so"
    535 
    536    gets you
    537 
    538      Could not load program xyzzy:
    539      rtld: 0712-001 Symbol __libc_freeres was referenced
    540      from module /foo/bar/vgpreload_core-ppc32-aix5.so(),
    541         but a runtime definition
    542             of the symbol was not found.
    543 */
    544 
    545 #endif // defined(VGO_aix5)
    546 
    547 /*--------------------------------------------------------------------*/
    548 /*---                                                              ---*/
    549 /*--------------------------------------------------------------------*/
    550