2 /*--------------------------------------------------------------------*/
3 /*--- Startup: create initial process image on AIX5 ---*/
4 /*--- initimg-aix5.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2006-2010 OpenWorks LLP
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.
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.
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
29 The GNU General Public License is contained in the file COPYING.
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.
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 */
61 #include "simple_huffman.c"
63 #if !defined(VGP_ppc32_aix5) && !defined(VGP_ppc64_aix5)
64 #error "This should only be compiled on AIX"
68 static void diagnose_load_failure ( void );
70 /* --- Create the client's initial memory image. --- */
72 IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii )
74 /* Set up an AIX5PreloadPage structure with the names of
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
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
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= "
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;
103 IIFinaliseImageInfo iifii;
104 VG_(memset)( &iifii, 0, sizeof(iifii) );
106 /* this can happen, if m_main decides to NULL it out */
107 if (VG_(args_the_exename) == NULL)
108 VG_(err_missing_prog)();
110 vg_assert( iicii.toolname );
111 pltool_len = VG_(strlen)( VG_(libdir) )
113 + VG_(strlen)( vgpreload_ )
114 + VG_(strlen)( iicii.toolname )
116 + VG_(strlen)(VG_PLATFORM)
119 vg_assert(pltool_len > 0);
120 pltool_str = VG_(malloc)( "initimg-aix5.ici.1", pltool_len );
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 );
132 plcore_len = VG_(strlen)( VG_(libdir) )
134 + VG_(strlen)( vgpreload_ )
135 + VG_(strlen)( core )
137 + VG_(strlen)(VG_PLATFORM)
140 vg_assert(plcore_len > 0);
141 plcore_str = VG_(malloc)( "initimg-aix5.ici.2", plcore_len );
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 );
153 errmsg_len = VG_(strlen)( errmsg_str )
156 ld_pre_str = VG_(getenv)("LD_PRELOAD");
157 if (ld_pre_str && VG_(strlen)(ld_pre_str) > 0) {
159 ld_pre_len = VG_(strlen)(ld_pre_str) + 1/*NUL*/;
160 ld_pre_str = VG_(malloc)( "initimg-aix5.ici.3", ld_pre_len );
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 );
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 );
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)");
179 have_tool_so = 0 == VG_(access)(pltool_str, True,False,True);
181 /* Figure out how much space is needed for an AIX5PreloadInfo
182 followed by the three preload strings. */
184 vg_assert((sizeof(AIX5PreloadPage) % 4) == 0); /* paranoia */
186 szB = sizeof(AIX5PreloadPage) + plcore_len
187 + (have_tool_so ? pltool_len : 0)
188 + (have_ld_pre ? ld_pre_len : 0)
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);
195 vg_assert(szB < szPG * VKI_PAGE_SIZE);
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);
202 VG_(err_config_error)("Can't allocate client page(s) "
204 pp = (AIX5PreloadPage*)sres.res;
206 VG_(debugLog)(2, "initimg", "preload page allocation succeeded at %p\n", pp);
208 /* Zero out the initial structure. */
209 VG_(memset)(pp, 0, sizeof(AIX5PreloadPage));
212 pc += sizeof(AIX5PreloadPage);
213 VG_(memcpy)(pc, plcore_str, plcore_len);
214 pp->off_preloadcorename = pc - (UChar*)pp;
217 VG_(memcpy)(pc, pltool_str, pltool_len);
218 pp->off_preloadtoolname = pc - (UChar*)pp;
222 VG_(memcpy)(pc, ld_pre_str, ld_pre_len);
223 pp->off_ld_preloadname = pc - (UChar*)pp;
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 */
230 vg_assert(pc <= ((UChar*)pp) - 1 + szPG * VKI_PAGE_SIZE);
232 VG_(free)(plcore_str);
233 VG_(free)(pltool_str);
235 /* Fill in all the other preload page fields that we can right
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;
245 vg_assert(__NR_AIX5_kwrite != __NR_AIX5_UNKNOWN);
246 pp->nr_kwrite = __NR_AIX5_kwrite; /* kwrite */
248 vg_assert(__NR_AIX5__exit != __NR_AIX5_UNKNOWN);
249 pp->nr__exit = __NR_AIX5__exit; /* _exit */
251 pp->p_diagnose_load_failure = &diagnose_load_failure;
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 */
263 /* --- Finalise the initial image and register state. --- */
265 static UChar unz_page[VKI_PAGE_SIZE];
267 static UInt compute_adler32 ( void* addr, UWord len )
271 UChar* buf = (UChar*)addr;
280 return (s2 << 16) + s1;
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).
289 void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
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. */
297 ThreadArchState* arch = &VG_(threads)[1].arch;
299 # if defined(VGP_ppc32_aix5)
301 vg_assert(0 == sizeof(VexGuestPPC32State) % 16);
303 /* Zero out the initial state, and set up the simulated FPU in a
305 LibVEX_GuestPPC32_initialise(&arch->vex);
307 /* Zero out the shadow areas. */
308 VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestPPC32State));
309 VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestPPC32State));
311 # else /* defined(VGP_ppc64_aix5) */
313 vg_assert(0 == sizeof(VexGuestPPC64State) % 16);
315 /* Zero out the initial state, and set up the simulated FPU in a
317 LibVEX_GuestPPC64_initialise(&arch->vex);
319 /* Zero out the shadow areas. */
320 VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestPPC64State));
321 VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestPPC64State));
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. */
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];
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];
368 # if defined(VGP_ppc32_aix5)
370 LibVEX_GuestPPC32_put_CR( (UWord)iifii.intregs37[32+1], &arch->vex );
371 LibVEX_GuestPPC32_put_XER( (UWord)iifii.intregs37[32+4], &arch->vex );
373 /* Set the cache line size (KLUDGE) */
374 VG_(machine_ppc32_set_clszB)( 128 );
376 # else /* defined(VGP_ppc64_aix5) */
378 LibVEX_GuestPPC64_put_CR( (UWord)iifii.intregs37[32+1], &arch->vex );
379 LibVEX_GuestPPC64_put_XER( (UWord)iifii.intregs37[32+4], &arch->vex );
381 /* Set the cache line size (KLUDGE) */
382 VG_(machine_ppc64_set_clszB)( 128 );
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
393 # if defined(VGP_ppc32_aix5)
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);
401 # else /* defined(VGP_ppc64_aix5) */
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);
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: */
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;
431 # if defined(VGP_ppc32_aix5)
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);
436 # else /* defined(VGP_ppc64_aix5) */
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);
443 arch->vex.guest_GPR3 = (UWord)iifii.preloadpage;
445 /* The rest of the preloadpage fields will already have been filled
446 in by VG_(setup_client_initial_image). So we're done. */
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));
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);
461 VG_(debugLog)(1, "initimg",
462 "decompress done, adler32s: act 0x%x, exp 0x%x\n",
463 adler32_act, iifii.adler32_exp );
465 VG_(memcpy)((void*)iifii.compressed_page, unz_page, VKI_PAGE_SIZE);
467 VG_(debugLog)(1, "initimg", "copy back done\n");
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));
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));
483 /* --- Diagnose preload failures. --- */
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. */
492 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
495 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
497 static void diagnose_load_failure ( void )
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
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]);
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");
526 /* Take the strings that this prints out and feed them
527 to /usr/sbin/execerror. For example, it might print
529 (ld 3 1 __libc_freeres /foo/bar/vgpreload_core-ppc32-aix5.so
534 "(ld 3 1 __libc_freeres /foo/bar/vgpreload_core-ppc32-aix5.so"
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.
545 #endif // defined(VGO_aix5)
547 /*--------------------------------------------------------------------*/
549 /*--------------------------------------------------------------------*/