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