blob: 5033be79e66975471a8c1df422b19732c2e2f65d [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
99 vg_assert( iicii.toolname );
sewardj2da47842006-10-17 01:23:07 +0000100 pltool_len = VG_(strlen)( VG_(libdir) )
101 + 1 /*slash*/
102 + VG_(strlen)(VG_PLATFORM)
103 + 1 /*slash*/
104 + VG_(strlen)( vgpreload_ )
sewardjf9d2f9b2006-11-17 20:00:57 +0000105 + VG_(strlen)( iicii.toolname )
sewardj2da47842006-10-17 01:23:07 +0000106 + VG_(strlen)( _so )
107 + 1 /*NUL*/;
108 vg_assert(pltool_len > 0);
109 pltool_str = VG_(malloc)( pltool_len );
110 pltool_str[0] = 0;
111 VG_(strcat)( pltool_str, VG_(libdir) );
112 VG_(strcat)( pltool_str, "/" );
113 VG_(strcat)( pltool_str, VG_PLATFORM );
114 VG_(strcat)( pltool_str, "/" );
115 VG_(strcat)( pltool_str, vgpreload_ );
sewardjf9d2f9b2006-11-17 20:00:57 +0000116 VG_(strcat)( pltool_str, iicii.toolname );
sewardj2da47842006-10-17 01:23:07 +0000117 VG_(strcat)( pltool_str, _so );
118 vg_assert( pltool_str[pltool_len-1] == 0);
119 vg_assert( VG_(strlen)(pltool_str) == pltool_len-1 );
120
121 plcore_len = VG_(strlen)( VG_(libdir) )
122 + 1 /*slash*/
123 + VG_(strlen)(VG_PLATFORM)
124 + 1 /*slash*/
125 + VG_(strlen)( vgpreload_core_so )
126 + 1 /*NUL*/;
127 vg_assert(plcore_len > 0);
128 plcore_str = VG_(malloc)( plcore_len );
129 plcore_str[0] = 0;
130 VG_(strcat)( plcore_str, VG_(libdir) );
131 VG_(strcat)( plcore_str, "/" );
132 VG_(strcat)( plcore_str, VG_PLATFORM );
133 VG_(strcat)( plcore_str, "/" );
134 VG_(strcat)( plcore_str, vgpreload_core_so );
135 vg_assert( plcore_str[plcore_len-1] == 0 );
136 vg_assert( VG_(strlen)(plcore_str) == plcore_len-1 );
137
138 errmsg_len = VG_(strlen)( errmsg_str )
139 + 1 /*NUL*/;
140
141 ld_pre_str = VG_(getenv)("LD_PRELOAD");
142 if (ld_pre_str && VG_(strlen)(ld_pre_str) > 0) {
143 have_ld_pre = True;
144 ld_pre_len = VG_(strlen)(ld_pre_str) + 1/*NUL*/;
145 ld_pre_str = VG_(malloc)( ld_pre_len );
146 ld_pre_str[0] = 0;
147 VG_(strcat)( ld_pre_str, VG_(getenv)("LD_PRELOAD") );
148 vg_assert( ld_pre_str[ld_pre_len-1] == 0);
149 vg_assert( VG_(strlen)( ld_pre_str ) == ld_pre_len - 1 );
150 } else {
151 have_ld_pre = False;
152 ld_pre_len = 0;
153 ld_pre_str = NULL;
154 }
155
156 VG_(debugLog)(1, "initimg", "plcore_str = '%s'\n", plcore_str );
157 VG_(debugLog)(1, "initimg", "pltool_str = '%s'\n", pltool_str );
158 VG_(debugLog)(1, "initimg", "ld_pre_str = '%s'\n", ld_pre_str );
159
160 if (0 != VG_(access)(plcore_str, True,False,True))
161 VG_(err_config_error)("Can't find core preload "
162 "(vgpreload_core.so)");
163
164 have_tool_so = 0 == VG_(access)(pltool_str, True,False,True);
165
166 /* Figure out how much space is needed for an AIX5PreloadInfo
167 followed by the three preload strings. */
168
169 vg_assert((sizeof(AIX5PreloadPage) % 4) == 0); /* paranoia */
170
171 szB = sizeof(AIX5PreloadPage) + plcore_len
172 + (have_tool_so ? pltool_len : 0)
173 + (have_ld_pre ? ld_pre_len : 0)
174 + errmsg_len;
175 szPG = VG_PGROUNDUP(szB+1) / VKI_PAGE_SIZE;
sewardjf9d2f9b2006-11-17 20:00:57 +0000176 VG_(debugLog)(2, "initimg",
177 "preload page size: %d bytes, %d pages\n", szB, szPG);
sewardj2da47842006-10-17 01:23:07 +0000178
179 vg_assert(szB > 0);
180 vg_assert(szB < szPG * VKI_PAGE_SIZE);
181
182 /* We'll need szPG pages of anonymous, rw-, client space (needs w
183 so we can write it here) */
184 sres = VG_(am_mmap_anon_float_client)
185 ( szPG * VKI_PAGE_SIZE, VKI_PROT_READ|VKI_PROT_WRITE);
186 if (sres.isError)
187 VG_(err_config_error)("Can't allocate client page(s) "
188 "for preload info");
189 pp = (AIX5PreloadPage*)sres.res;
190
191 VG_(debugLog)(2, "initimg", "preload page allocation succeeded at %p\n", pp);
192
193 /* Zero out the initial structure. */
194 VG_(memset)(pp, 0, sizeof(AIX5PreloadPage));
195
196 pc = (UChar*)pp;
197 pc += sizeof(AIX5PreloadPage);
198 VG_(memcpy)(pc, plcore_str, plcore_len);
199 pp->off_preloadcorename = pc - (UChar*)pp;
200 pc += plcore_len;
201 if (have_tool_so) {
202 VG_(memcpy)(pc, pltool_str, pltool_len);
203 pp->off_preloadtoolname = pc - (UChar*)pp;
204 pc += pltool_len;
205 }
206 if (have_ld_pre) {
207 VG_(memcpy)(pc, ld_pre_str, ld_pre_len);
208 pp->off_ld_preloadname = pc - (UChar*)pp;
209 pc += ld_pre_len;
210 }
211 VG_(memcpy)(pc, errmsg_str, errmsg_len);
212 pp->off_errmsg = pc - (UChar*)pp;
213 pp->len_errmsg = errmsg_len - 1; /* -1: skip terminating NUL */
214
215 vg_assert(pc <= ((UChar*)pp) - 1 + szPG * VKI_PAGE_SIZE);
216
217 VG_(free)(plcore_str);
218 VG_(free)(pltool_str);
219
220 /* Fill in all the other preload page fields that we can right
221 now. */
222# if defined(VGP_ppc32_aix5)
223 vg_assert(__NR_AIX5___loadx != __NR_AIX5_UNKNOWN);
224 pp->nr_load = __NR_AIX5___loadx;
225# else /* defined(VGP_ppc64_aix5) */
226 vg_assert(__NR_AIX5_kload != __NR_AIX5_UNKNOWN);
227 pp->nr_load = __NR_AIX5_kload;
228# endif
229
230 vg_assert(__NR_AIX5_kwrite != __NR_AIX5_UNKNOWN);
231 pp->nr_kwrite = __NR_AIX5_kwrite; /* kwrite */
232
233 vg_assert(__NR_AIX5__exit != __NR_AIX5_UNKNOWN);
234 pp->nr__exit = __NR_AIX5__exit; /* _exit */
235
236 pp->p_diagnose_load_failure = &diagnose_load_failure;
237
sewardjf9d2f9b2006-11-17 20:00:57 +0000238 iifii.preloadpage = pp;
239 iifii.intregs37 = iicii.intregs37;
240 iifii.initial_client_SP = iicii.intregs37[1]; /* r1 */
241 iifii.compressed_page = VG_PGROUNDDN((Addr)iicii.bootblock);
242 iifii.adler32_exp = iicii.adler32_exp;
243 iifii.clstack_max_size = 0; /* we don't know yet */
244 return iifii;
sewardj2da47842006-10-17 01:23:07 +0000245}
246
247
248/* --- Finalise the initial image and register state. --- */
249
250static UChar unz_page[VKI_PAGE_SIZE];
251
252static UInt compute_adler32 ( void* addr, UWord len )
253{
254 UInt s1 = 1;
255 UInt s2 = 0;
256 UChar* buf = (UChar*)addr;
257 while (len > 0) {
258 s1 += buf[0];
259 s2 += s1;
260 s1 %= 65521;
261 s2 %= 65521;
262 len--;
263 buf++;
264 }
265 return (s2 << 16) + s1;
266}
267
sewardjf9d2f9b2006-11-17 20:00:57 +0000268/* Just before starting the client, we may need to make final
269 adjustments to its initial image. Also we need to set up the VEX
270 guest state for thread 1 (the root thread) and copy in essential
271 starting values. This is handed the IIFinaliseImageInfo created by
272 VG_(ii_create_image).
273*/
274void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
sewardj2da47842006-10-17 01:23:07 +0000275{
sewardjf9d2f9b2006-11-17 20:00:57 +0000276 UInt adler32_act;
sewardj2da47842006-10-17 01:23:07 +0000277 SysRes sres;
278 /* On AIX we get a block of 37 words telling us the initial state
279 for (GPR0 .. GPR31, PC, CR, LR, CTR, XER), and we start with all
280 the other registers zeroed. */
281
sewardjf9d2f9b2006-11-17 20:00:57 +0000282 ThreadArchState* arch = &VG_(threads)[1].arch;
283
sewardj2da47842006-10-17 01:23:07 +0000284# if defined(VGP_ppc32_aix5)
285
286 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
287
288 /* Zero out the initial state, and set up the simulated FPU in a
289 sane way. */
290 LibVEX_GuestPPC32_initialise(&arch->vex);
291
292 /* Zero out the shadow area. */
293 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
294
295# else /* defined(VGP_ppc64_aix5) */
296
297 vg_assert(0 == sizeof(VexGuestPPC64State) % 8);
298
299 /* Zero out the initial state, and set up the simulated FPU in a
300 sane way. */
301 LibVEX_GuestPPC64_initialise(&arch->vex);
302
303 /* Zero out the shadow area. */
304 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
305
306# endif
307
sewardjf9d2f9b2006-11-17 20:00:57 +0000308 /* iifii.intregs37 contains the integer register state as it needs
sewardj2da47842006-10-17 01:23:07 +0000309 to be at client startup. These values are supplied by the
310 launcher. The 37 regs are:initial values from launcher for:
311 GPR0 .. GPR31, PC, CR, LR, CTR, XER. */
312
313 /* Put essential stuff into the new state. */
sewardjf9d2f9b2006-11-17 20:00:57 +0000314 arch->vex.guest_GPR0 = (UWord)iifii.intregs37[0];
315 arch->vex.guest_GPR1 = (UWord)iifii.intregs37[1];
316 arch->vex.guest_GPR2 = (UWord)iifii.intregs37[2];
317 arch->vex.guest_GPR3 = (UWord)iifii.intregs37[3];
318 arch->vex.guest_GPR4 = (UWord)iifii.intregs37[4];
319 arch->vex.guest_GPR5 = (UWord)iifii.intregs37[5];
320 arch->vex.guest_GPR6 = (UWord)iifii.intregs37[6];
321 arch->vex.guest_GPR7 = (UWord)iifii.intregs37[7];
322 arch->vex.guest_GPR8 = (UWord)iifii.intregs37[8];
323 arch->vex.guest_GPR9 = (UWord)iifii.intregs37[9];
324 arch->vex.guest_GPR10 = (UWord)iifii.intregs37[10];
325 arch->vex.guest_GPR11 = (UWord)iifii.intregs37[11];
326 arch->vex.guest_GPR12 = (UWord)iifii.intregs37[12];
327 arch->vex.guest_GPR13 = (UWord)iifii.intregs37[13];
328 arch->vex.guest_GPR14 = (UWord)iifii.intregs37[14];
329 arch->vex.guest_GPR15 = (UWord)iifii.intregs37[15];
330 arch->vex.guest_GPR16 = (UWord)iifii.intregs37[16];
331 arch->vex.guest_GPR17 = (UWord)iifii.intregs37[17];
332 arch->vex.guest_GPR18 = (UWord)iifii.intregs37[18];
333 arch->vex.guest_GPR19 = (UWord)iifii.intregs37[19];
334 arch->vex.guest_GPR20 = (UWord)iifii.intregs37[20];
335 arch->vex.guest_GPR21 = (UWord)iifii.intregs37[21];
336 arch->vex.guest_GPR22 = (UWord)iifii.intregs37[22];
337 arch->vex.guest_GPR23 = (UWord)iifii.intregs37[23];
338 arch->vex.guest_GPR24 = (UWord)iifii.intregs37[24];
339 arch->vex.guest_GPR25 = (UWord)iifii.intregs37[25];
340 arch->vex.guest_GPR26 = (UWord)iifii.intregs37[26];
341 arch->vex.guest_GPR27 = (UWord)iifii.intregs37[27];
342 arch->vex.guest_GPR28 = (UWord)iifii.intregs37[28];
343 arch->vex.guest_GPR29 = (UWord)iifii.intregs37[29];
344 arch->vex.guest_GPR30 = (UWord)iifii.intregs37[30];
345 arch->vex.guest_GPR31 = (UWord)iifii.intregs37[31];
sewardj2da47842006-10-17 01:23:07 +0000346
sewardjf9d2f9b2006-11-17 20:00:57 +0000347 arch->vex.guest_CIA = (UWord)iifii.intregs37[32+0];
348 arch->vex.guest_LR = (UWord)iifii.intregs37[32+2];
349 arch->vex.guest_CTR = (UWord)iifii.intregs37[32+3];
sewardj2da47842006-10-17 01:23:07 +0000350
351# if defined(VGP_ppc32_aix5)
352
sewardjf9d2f9b2006-11-17 20:00:57 +0000353 LibVEX_GuestPPC32_put_CR( (UWord)iifii.intregs37[32+1], &arch->vex );
354 LibVEX_GuestPPC32_put_XER( (UWord)iifii.intregs37[32+4], &arch->vex );
sewardj2da47842006-10-17 01:23:07 +0000355
356 /* Set the cache line size (KLUDGE) */
357 VG_(machine_ppc32_set_clszB)( 128 );
358
359# else /* defined(VGP_ppc64_aix5) */
360
sewardjf9d2f9b2006-11-17 20:00:57 +0000361 LibVEX_GuestPPC64_put_CR( (UWord)iifii.intregs37[32+1], &arch->vex );
362 LibVEX_GuestPPC64_put_XER( (UWord)iifii.intregs37[32+4], &arch->vex );
sewardj2da47842006-10-17 01:23:07 +0000363
364 /* Set the cache line size (KLUDGE) */
365 VG_(machine_ppc64_set_clszB)( 128 );
366
367# endif
368
369 /* Fix up the client's command line. Its argc/v/envp is in r3/4/5
370 (32-bit AIX) or r14/15/16 (64-bit AIX). but that is for the
371 Valgrind invokation as a whole. Hence we need to decrement argc
372 and advance argv to step over the args for Valgrind, and the
373 name of the Valgrind tool exe bogusly inserted by the launcher
374 (hence the "+1"). */
375
376# if defined(VGP_ppc32_aix5)
377
sewardjc271ec82007-02-27 22:36:14 +0000378 { UWord n_vargs = VG_(sizeXA)( VG_(args_for_valgrind) );
379 vg_assert(arch->vex.guest_GPR3 >= 1 + n_vargs);
380 arch->vex.guest_GPR3 -= (1 + n_vargs);
381 arch->vex.guest_GPR4 += sizeof(UWord) * (1 + n_vargs);
382 }
sewardj2da47842006-10-17 01:23:07 +0000383
384# else /* defined(VGP_ppc64_aix5) */
385
sewardjc271ec82007-02-27 22:36:14 +0000386 { UWord n_vargs = VG_(sizeXA)( VG_(args_for_valgrind) );
387 vg_assert(arch->vex.guest_GPR14 >= 1 + n_vargs);
388 arch->vex.guest_GPR14 -= (1 + n_vargs);
389 arch->vex.guest_GPR15 += sizeof(UWord) * (1 + n_vargs);
390 }
sewardj2da47842006-10-17 01:23:07 +0000391
392# endif
393
394 /* At this point the guest register state is correct for client
395 startup. However, that's not where we want to start; in fact we
sewardjf9d2f9b2006-11-17 20:00:57 +0000396 want to start at VG_(ppc{32,64}_aix5_do_preloads_then_start_client),
397 passing it iifii.preloadpage in r3. This will load the core/tool
sewardj2da47842006-10-17 01:23:07 +0000398 preload .so's, then restore r2-r10 from what's stashed in the
399 preloadpage, and then start the client really. Hence: */
400
401 /* Save r2-r10 and the client start point in preloadpage */
sewardjf9d2f9b2006-11-17 20:00:57 +0000402 iifii.preloadpage->r2 = (ULong)arch->vex.guest_GPR2;
403 iifii.preloadpage->r3 = (ULong)arch->vex.guest_GPR3;
404 iifii.preloadpage->r4 = (ULong)arch->vex.guest_GPR4;
405 iifii.preloadpage->r5 = (ULong)arch->vex.guest_GPR5;
406 iifii.preloadpage->r6 = (ULong)arch->vex.guest_GPR6;
407 iifii.preloadpage->r7 = (ULong)arch->vex.guest_GPR7;
408 iifii.preloadpage->r8 = (ULong)arch->vex.guest_GPR8;
409 iifii.preloadpage->r9 = (ULong)arch->vex.guest_GPR9;
410 iifii.preloadpage->r10 = (ULong)arch->vex.guest_GPR10;
411 iifii.preloadpage->client_start = (ULong)arch->vex.guest_CIA;
sewardj2da47842006-10-17 01:23:07 +0000412
413
414# if defined(VGP_ppc32_aix5)
415
416 /* Set up to start at VG_(ppc32_aix5_do_preloads_then_start_client) */
417 arch->vex.guest_CIA = (UWord)&VG_(ppc32_aix5_do_preloads_then_start_client);
418
419# else /* defined(VGP_ppc64_aix5) */
420
421 /* Set up to start at VG_(ppc64_aix5_do_preloads_then_start_client) */
422 arch->vex.guest_CIA = (UWord)&VG_(ppc64_aix5_do_preloads_then_start_client);
423
424# endif
425
sewardjf9d2f9b2006-11-17 20:00:57 +0000426 arch->vex.guest_GPR3 = (UWord)iifii.preloadpage;
sewardj2da47842006-10-17 01:23:07 +0000427
428 /* The rest of the preloadpage fields will already have been filled
429 in by VG_(setup_client_initial_image). So we're done. */
430
431 /* Finally, decompress the page compressed by the launcher. We
432 can't do this any earlier, because the page is (effectively)
sewardjf9d2f9b2006-11-17 20:00:57 +0000433 decompressed in place, which trashes iifii.intregs37. So we have
434 to wait till this point, at which we're done with iifii.intregs37
sewardj2da47842006-10-17 01:23:07 +0000435 (to be precise, with what it points at). */
436 VG_(debugLog)(1, "initimg", "decompressing page at %p\n",
sewardjf9d2f9b2006-11-17 20:00:57 +0000437 (void*)iifii.compressed_page);
438 vg_assert(VG_IS_PAGE_ALIGNED(iifii.compressed_page));
sewardj2da47842006-10-17 01:23:07 +0000439
sewardjf9d2f9b2006-11-17 20:00:57 +0000440 Huffman_Uncompress( (void*)iifii.compressed_page, unz_page,
sewardj2da47842006-10-17 01:23:07 +0000441 VKI_PAGE_SIZE, VKI_PAGE_SIZE );
442 adler32_act = compute_adler32(unz_page, VKI_PAGE_SIZE);
443
444 VG_(debugLog)(1, "initimg",
445 "decompress done, adler32s: act 0x%x, exp 0x%x\n",
sewardjf9d2f9b2006-11-17 20:00:57 +0000446 adler32_act, iifii.adler32_exp );
sewardj2da47842006-10-17 01:23:07 +0000447
sewardjf9d2f9b2006-11-17 20:00:57 +0000448 VG_(memcpy)((void*)iifii.compressed_page, unz_page, VKI_PAGE_SIZE);
sewardj2da47842006-10-17 01:23:07 +0000449
450 VG_(debugLog)(1, "initimg", "copy back done\n");
451
452 /* Tell the tool that we just wrote to the registers. */
453 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
454 sizeof(VexGuestArchState));
455
456 /* Determine the brk limit. */
457 VG_(debugLog)(1, "initimg", "establishing current brk ..\n");
458 vg_assert(__NR_AIX5_sbrk != __NR_AIX5_UNKNOWN);
459 sres = VG_(do_syscall1)(__NR_AIX5_sbrk, 0);
460 vg_assert(sres.err == 0); /* assert no error */
461 VG_(brk_base) = VG_(brk_limit) = sres.res;
462 VG_(debugLog)(1, "initimg", ".. brk = %p\n", (void*)VG_(brk_base));
463}
464
465
466/* --- Diagnose preload failures. --- */
467
468/* This is a nasty but effective kludge. The address of the following
469 function is put into the preload page. So, if a preload failure
470 happens, we call here to get helpful info printed out (the call
471 site is in m_trampoline.S). This is a dirty hack (1) because
472 diagnose_load_failure runs on the simulated CPU, not the real one
473 and (2) because it induces a libc dependency. Oh well. */
474
475/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
476#include <stdlib.h>
477#include <sys/ldr.h>
478/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
479
480static void diagnose_load_failure ( void )
481{
482# define NBUF 1024
483 UChar buf[NBUF];
484 VG_(debugLog)(0, "initimg", "Diagnosing load failure\n");
485 if (sizeof(void*) == 8) {
486 VG_(debugLog)(0, "initimg", "Can't safely do loadquery() "
487 "in 64-bit mode. Sorry.\n");
488 /* because this requires dynamic linking to be working (IIRC)
489 and it isn't; the tool file's dynamic linking was never done,
490 because it was loaded by the bootstrap stub, which simply did
491 sys_kload() but didn't make usla do the relevant
492 relocations. */
493 } else {
494 UChar** p;
495 Int r = loadquery(L_GETMESSAGES, buf, NBUF);
496 VG_(debugLog)(0, "initimg", "loadquery returned %d (0 = success)\n", r);
497 p = (UChar**)(&buf[0]);
498 for (; *p; p++)
499 VG_(debugLog)(0, "initimg", "\"%s\"\n", *p);
500 VG_(debugLog)(0, "initimg", "Use /usr/sbin/execerror to make "
501 "sense of above string(s)\n");
502 VG_(debugLog)(0, "initimg", "See also comments at the bottom of\n");
503 VG_(debugLog)(0, "initimg", "coregrind/m_initimg/"
504 "initimg-aix5.c (in Valgrind sources)\n");
505 }
506# undef NBUF
507}
508
509/* Take the strings that this prints out and feed them
510 to /usr/sbin/execerror. For example, it might print
511
512 (ld 3 1 __libc_freeres /foo/bar/ppc32-aix5/vgpreload_core.so
513
514 in which case
515
516 $ execerror xyzzy \
517 "(ld 3 1 __libc_freeres /foo/bar/ppc32-aix5/vgpreload_core.so"
518
519 gets you
520
521 Could not load program xyzzy:
522 rtld: 0712-001 Symbol __libc_freeres was referenced
523 from module /foo/bar/ppc32-aix5/vgpreload_core.so(),
524 but a runtime definition
525 of the symbol was not found.
526*/
527
528/*--------------------------------------------------------------------*/
529/*--- initimg-aix5.c ---*/
530/*--------------------------------------------------------------------*/