]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_initimg/initimg-aix5.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_initimg / initimg-aix5.c
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@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 /*--------------------------------------------------------------------*/