blob: a1d3b1671ad9fe033786a6ea2b0b4a163d474dd5 [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
11 Copyright (C) 2006-2006 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
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"
41#include "pub_core_clientstate.h"
42#include "pub_core_aspacemgr.h"
43#include "pub_core_mallocfree.h"
44#include "pub_core_machine.h"
45#include "pub_core_ume.h"
46#include "pub_core_options.h"
47#include "pub_core_threadstate.h" /* ThreadArchState */
48#include "pub_core_tooliface.h" /* VG_TRACK */
49#include "pub_core_trampoline.h" /* VG_(ppc32_aix5_do_preloads_then_start_client) */
50#include "pub_core_syscall.h" // VG_(do_syscall1)
51#include "pub_core_initimg.h" /* self */
52
53#include "simple_huffman.c"
54
55#if !defined(VGP_ppc32_aix5) && !defined(VGP_ppc64_aix5)
56#error "This should only be compiled on AIX"
57#endif
58
59
60static void diagnose_load_failure ( void );
61
62/* --- Create the client's initial memory image. --- */
63
64ClientInitImgInfo
65 VG_(setup_client_initial_image)(
66 /*IN*/ HChar** argv,
67 /*IN*/ HChar** envp,
68 /*IN*/ HChar* toolname,
69 /*IN*/ Addr clstack_top,
70 /*IN*/ SizeT clstack_max_size
71 )
72{
73 ClientInitImgInfo ciii;
74
75 /* Set up an AIX5PreloadPage structure with the names of
76
77 $VALGRIND_LIB/PLATFORM/vgpreload_core.so
78 $VALGRIND_LIB/PLATFORM/vgpreload_TOOL.so, if it exists
79 xxx in "LD_PRELOAD=xxx", if it exists
80
81 The client is started by running (on the simulator, of course)
82 VG_(ppc{32,64}_aix5_do_preloads_then_start_client), which uses
83 __loadx/_kload to load these .so's. When the preloading is
84 done, various guest registers are restored to what they are
85 really supposed to be at client startup, so these values too are
86 stored in the AIX5PreloadPage. Finally, we jump to the client's
87 entry point address.
88 */
89 const HChar* _so = ".so";
90 const HChar* vgpreload_ = "vgpreload_";
91 const HChar* vgpreload_core_so = "vgpreload_core.so";
92 const HChar* errmsg_str
93 = "valgrind: FATAL: core/tool/LD_PRELOAD= "
94 "preload failed.\n";
95 Int plcore_len, pltool_len, ld_pre_len, errmsg_len;
96 HChar *plcore_str, *pltool_str, *ld_pre_str;
97 Bool have_tool_so, have_ld_pre;
98
99 AIX5PreloadPage* pp;
100 UChar* pc;
101 Int szB, szPG;
102 SysRes sres;
103
104 vg_assert( toolname );
105 pltool_len = VG_(strlen)( VG_(libdir) )
106 + 1 /*slash*/
107 + VG_(strlen)(VG_PLATFORM)
108 + 1 /*slash*/
109 + VG_(strlen)( vgpreload_ )
110 + VG_(strlen)( toolname )
111 + VG_(strlen)( _so )
112 + 1 /*NUL*/;
113 vg_assert(pltool_len > 0);
114 pltool_str = VG_(malloc)( pltool_len );
115 pltool_str[0] = 0;
116 VG_(strcat)( pltool_str, VG_(libdir) );
117 VG_(strcat)( pltool_str, "/" );
118 VG_(strcat)( pltool_str, VG_PLATFORM );
119 VG_(strcat)( pltool_str, "/" );
120 VG_(strcat)( pltool_str, vgpreload_ );
121 VG_(strcat)( pltool_str, toolname );
122 VG_(strcat)( pltool_str, _so );
123 vg_assert( pltool_str[pltool_len-1] == 0);
124 vg_assert( VG_(strlen)(pltool_str) == pltool_len-1 );
125
126 plcore_len = VG_(strlen)( VG_(libdir) )
127 + 1 /*slash*/
128 + VG_(strlen)(VG_PLATFORM)
129 + 1 /*slash*/
130 + VG_(strlen)( vgpreload_core_so )
131 + 1 /*NUL*/;
132 vg_assert(plcore_len > 0);
133 plcore_str = VG_(malloc)( plcore_len );
134 plcore_str[0] = 0;
135 VG_(strcat)( plcore_str, VG_(libdir) );
136 VG_(strcat)( plcore_str, "/" );
137 VG_(strcat)( plcore_str, VG_PLATFORM );
138 VG_(strcat)( plcore_str, "/" );
139 VG_(strcat)( plcore_str, vgpreload_core_so );
140 vg_assert( plcore_str[plcore_len-1] == 0 );
141 vg_assert( VG_(strlen)(plcore_str) == plcore_len-1 );
142
143 errmsg_len = VG_(strlen)( errmsg_str )
144 + 1 /*NUL*/;
145
146 ld_pre_str = VG_(getenv)("LD_PRELOAD");
147 if (ld_pre_str && VG_(strlen)(ld_pre_str) > 0) {
148 have_ld_pre = True;
149 ld_pre_len = VG_(strlen)(ld_pre_str) + 1/*NUL*/;
150 ld_pre_str = VG_(malloc)( ld_pre_len );
151 ld_pre_str[0] = 0;
152 VG_(strcat)( ld_pre_str, VG_(getenv)("LD_PRELOAD") );
153 vg_assert( ld_pre_str[ld_pre_len-1] == 0);
154 vg_assert( VG_(strlen)( ld_pre_str ) == ld_pre_len - 1 );
155 } else {
156 have_ld_pre = False;
157 ld_pre_len = 0;
158 ld_pre_str = NULL;
159 }
160
161 VG_(debugLog)(1, "initimg", "plcore_str = '%s'\n", plcore_str );
162 VG_(debugLog)(1, "initimg", "pltool_str = '%s'\n", pltool_str );
163 VG_(debugLog)(1, "initimg", "ld_pre_str = '%s'\n", ld_pre_str );
164
165 if (0 != VG_(access)(plcore_str, True,False,True))
166 VG_(err_config_error)("Can't find core preload "
167 "(vgpreload_core.so)");
168
169 have_tool_so = 0 == VG_(access)(pltool_str, True,False,True);
170
171 /* Figure out how much space is needed for an AIX5PreloadInfo
172 followed by the three preload strings. */
173
174 vg_assert((sizeof(AIX5PreloadPage) % 4) == 0); /* paranoia */
175
176 szB = sizeof(AIX5PreloadPage) + plcore_len
177 + (have_tool_so ? pltool_len : 0)
178 + (have_ld_pre ? ld_pre_len : 0)
179 + errmsg_len;
180 szPG = VG_PGROUNDUP(szB+1) / VKI_PAGE_SIZE;
181 VG_(debugLog)(2, "initimg", "preload page size: %d bytes, %d pages\n", szB, szPG);
182
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
242 ciii.preloadpage = pp;
243 ciii.intregs37 = 0; /* filled in in m_main.c */
244 return ciii;
245}
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
268void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch,
269 ClientInitImgInfo ciii )
270{
271 UInt adler32_act;
272 SysRes sres;
273 /* On AIX we get a block of 37 words telling us the initial state
274 for (GPR0 .. GPR31, PC, CR, LR, CTR, XER), and we start with all
275 the other registers zeroed. */
276
277# if defined(VGP_ppc32_aix5)
278
279 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
280
281 /* Zero out the initial state, and set up the simulated FPU in a
282 sane way. */
283 LibVEX_GuestPPC32_initialise(&arch->vex);
284
285 /* Zero out the shadow area. */
286 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
287
288# else /* defined(VGP_ppc64_aix5) */
289
290 vg_assert(0 == sizeof(VexGuestPPC64State) % 8);
291
292 /* Zero out the initial state, and set up the simulated FPU in a
293 sane way. */
294 LibVEX_GuestPPC64_initialise(&arch->vex);
295
296 /* Zero out the shadow area. */
297 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
298
299# endif
300
301 /* ciii.intregs37 contains the integer register state as it needs
302 to be at client startup. These values are supplied by the
303 launcher. The 37 regs are:initial values from launcher for:
304 GPR0 .. GPR31, PC, CR, LR, CTR, XER. */
305
306 /* Put essential stuff into the new state. */
307 arch->vex.guest_GPR0 = (UWord)ciii.intregs37[0];
308 arch->vex.guest_GPR1 = (UWord)ciii.intregs37[1];
309 arch->vex.guest_GPR2 = (UWord)ciii.intregs37[2];
310 arch->vex.guest_GPR3 = (UWord)ciii.intregs37[3];
311 arch->vex.guest_GPR4 = (UWord)ciii.intregs37[4];
312 arch->vex.guest_GPR5 = (UWord)ciii.intregs37[5];
313 arch->vex.guest_GPR6 = (UWord)ciii.intregs37[6];
314 arch->vex.guest_GPR7 = (UWord)ciii.intregs37[7];
315 arch->vex.guest_GPR8 = (UWord)ciii.intregs37[8];
316 arch->vex.guest_GPR9 = (UWord)ciii.intregs37[9];
317 arch->vex.guest_GPR10 = (UWord)ciii.intregs37[10];
318 arch->vex.guest_GPR11 = (UWord)ciii.intregs37[11];
319 arch->vex.guest_GPR12 = (UWord)ciii.intregs37[12];
320 arch->vex.guest_GPR13 = (UWord)ciii.intregs37[13];
321 arch->vex.guest_GPR14 = (UWord)ciii.intregs37[14];
322 arch->vex.guest_GPR15 = (UWord)ciii.intregs37[15];
323 arch->vex.guest_GPR16 = (UWord)ciii.intregs37[16];
324 arch->vex.guest_GPR17 = (UWord)ciii.intregs37[17];
325 arch->vex.guest_GPR18 = (UWord)ciii.intregs37[18];
326 arch->vex.guest_GPR19 = (UWord)ciii.intregs37[19];
327 arch->vex.guest_GPR20 = (UWord)ciii.intregs37[20];
328 arch->vex.guest_GPR21 = (UWord)ciii.intregs37[21];
329 arch->vex.guest_GPR22 = (UWord)ciii.intregs37[22];
330 arch->vex.guest_GPR23 = (UWord)ciii.intregs37[23];
331 arch->vex.guest_GPR24 = (UWord)ciii.intregs37[24];
332 arch->vex.guest_GPR25 = (UWord)ciii.intregs37[25];
333 arch->vex.guest_GPR26 = (UWord)ciii.intregs37[26];
334 arch->vex.guest_GPR27 = (UWord)ciii.intregs37[27];
335 arch->vex.guest_GPR28 = (UWord)ciii.intregs37[28];
336 arch->vex.guest_GPR29 = (UWord)ciii.intregs37[29];
337 arch->vex.guest_GPR30 = (UWord)ciii.intregs37[30];
338 arch->vex.guest_GPR31 = (UWord)ciii.intregs37[31];
339
340 arch->vex.guest_CIA = (UWord)ciii.intregs37[32+0];
341 arch->vex.guest_LR = (UWord)ciii.intregs37[32+2];
342 arch->vex.guest_CTR = (UWord)ciii.intregs37[32+3];
343
344# if defined(VGP_ppc32_aix5)
345
346 LibVEX_GuestPPC32_put_CR( (UWord)ciii.intregs37[32+1], &arch->vex );
347 LibVEX_GuestPPC32_put_XER( (UWord)ciii.intregs37[32+4], &arch->vex );
348
349 /* Set the cache line size (KLUDGE) */
350 VG_(machine_ppc32_set_clszB)( 128 );
351
352# else /* defined(VGP_ppc64_aix5) */
353
354 LibVEX_GuestPPC64_put_CR( (UWord)ciii.intregs37[32+1], &arch->vex );
355 LibVEX_GuestPPC64_put_XER( (UWord)ciii.intregs37[32+4], &arch->vex );
356
357 /* Set the cache line size (KLUDGE) */
358 VG_(machine_ppc64_set_clszB)( 128 );
359
360# endif
361
362 /* Fix up the client's command line. Its argc/v/envp is in r3/4/5
363 (32-bit AIX) or r14/15/16 (64-bit AIX). but that is for the
364 Valgrind invokation as a whole. Hence we need to decrement argc
365 and advance argv to step over the args for Valgrind, and the
366 name of the Valgrind tool exe bogusly inserted by the launcher
367 (hence the "+1"). */
368
369# if defined(VGP_ppc32_aix5)
370
371 vg_assert(arch->vex.guest_GPR3 >= 1 + VG_(args_for_valgrind).used);
372 arch->vex.guest_GPR3 -= (1 + VG_(args_for_valgrind).used);
373 arch->vex.guest_GPR4 += sizeof(UWord) * (1 + VG_(args_for_valgrind).used);
374
375# else /* defined(VGP_ppc64_aix5) */
376
377 vg_assert(arch->vex.guest_GPR14 >= 1 + VG_(args_for_valgrind).used);
378 arch->vex.guest_GPR14 -= (1 + VG_(args_for_valgrind).used);
379 arch->vex.guest_GPR15 += sizeof(UWord) * (1 + VG_(args_for_valgrind).used);
380
381# endif
382
383 /* At this point the guest register state is correct for client
384 startup. However, that's not where we want to start; in fact we
385 want to start at VG_(ppc{3,64}2_aix5_do_preloads_then_start_client),
386 passing it ciii.preloadpage in r3. This will load the core/tool
387 preload .so's, then restore r2-r10 from what's stashed in the
388 preloadpage, and then start the client really. Hence: */
389
390 /* Save r2-r10 and the client start point in preloadpage */
391 ciii.preloadpage->r2 = (ULong)arch->vex.guest_GPR2;
392 ciii.preloadpage->r3 = (ULong)arch->vex.guest_GPR3;
393 ciii.preloadpage->r4 = (ULong)arch->vex.guest_GPR4;
394 ciii.preloadpage->r5 = (ULong)arch->vex.guest_GPR5;
395 ciii.preloadpage->r6 = (ULong)arch->vex.guest_GPR6;
396 ciii.preloadpage->r7 = (ULong)arch->vex.guest_GPR7;
397 ciii.preloadpage->r8 = (ULong)arch->vex.guest_GPR8;
398 ciii.preloadpage->r9 = (ULong)arch->vex.guest_GPR9;
399 ciii.preloadpage->r10 = (ULong)arch->vex.guest_GPR10;
400 ciii.preloadpage->client_start = (ULong)arch->vex.guest_CIA;
401
402
403# if defined(VGP_ppc32_aix5)
404
405 /* Set up to start at VG_(ppc32_aix5_do_preloads_then_start_client) */
406 arch->vex.guest_CIA = (UWord)&VG_(ppc32_aix5_do_preloads_then_start_client);
407
408# else /* defined(VGP_ppc64_aix5) */
409
410 /* Set up to start at VG_(ppc64_aix5_do_preloads_then_start_client) */
411 arch->vex.guest_CIA = (UWord)&VG_(ppc64_aix5_do_preloads_then_start_client);
412
413# endif
414
415 arch->vex.guest_GPR3 = (UWord)ciii.preloadpage;
416
417 /* The rest of the preloadpage fields will already have been filled
418 in by VG_(setup_client_initial_image). So we're done. */
419
420 /* Finally, decompress the page compressed by the launcher. We
421 can't do this any earlier, because the page is (effectively)
422 decompressed in place, which trashes ciii.intregs37. So we have
423 to wait till this point, at which we're done with ciii.intregs37
424 (to be precise, with what it points at). */
425 VG_(debugLog)(1, "initimg", "decompressing page at %p\n",
426 (void*)ciii.compressed_page);
427 vg_assert(VG_IS_PAGE_ALIGNED(ciii.compressed_page));
428
429 Huffman_Uncompress( (void*)ciii.compressed_page, unz_page,
430 VKI_PAGE_SIZE, VKI_PAGE_SIZE );
431 adler32_act = compute_adler32(unz_page, VKI_PAGE_SIZE);
432
433 VG_(debugLog)(1, "initimg",
434 "decompress done, adler32s: act 0x%x, exp 0x%x\n",
435 adler32_act, ciii.adler32_exp );
436
437 VG_(memcpy)((void*)ciii.compressed_page, unz_page, VKI_PAGE_SIZE);
438
439 VG_(debugLog)(1, "initimg", "copy back done\n");
440
441 /* Tell the tool that we just wrote to the registers. */
442 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
443 sizeof(VexGuestArchState));
444
445 /* Determine the brk limit. */
446 VG_(debugLog)(1, "initimg", "establishing current brk ..\n");
447 vg_assert(__NR_AIX5_sbrk != __NR_AIX5_UNKNOWN);
448 sres = VG_(do_syscall1)(__NR_AIX5_sbrk, 0);
449 vg_assert(sres.err == 0); /* assert no error */
450 VG_(brk_base) = VG_(brk_limit) = sres.res;
451 VG_(debugLog)(1, "initimg", ".. brk = %p\n", (void*)VG_(brk_base));
452}
453
454
455/* --- Diagnose preload failures. --- */
456
457/* This is a nasty but effective kludge. The address of the following
458 function is put into the preload page. So, if a preload failure
459 happens, we call here to get helpful info printed out (the call
460 site is in m_trampoline.S). This is a dirty hack (1) because
461 diagnose_load_failure runs on the simulated CPU, not the real one
462 and (2) because it induces a libc dependency. Oh well. */
463
464/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
465#include <stdlib.h>
466#include <sys/ldr.h>
467/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
468
469static void diagnose_load_failure ( void )
470{
471# define NBUF 1024
472 UChar buf[NBUF];
473 VG_(debugLog)(0, "initimg", "Diagnosing load failure\n");
474 if (sizeof(void*) == 8) {
475 VG_(debugLog)(0, "initimg", "Can't safely do loadquery() "
476 "in 64-bit mode. Sorry.\n");
477 /* because this requires dynamic linking to be working (IIRC)
478 and it isn't; the tool file's dynamic linking was never done,
479 because it was loaded by the bootstrap stub, which simply did
480 sys_kload() but didn't make usla do the relevant
481 relocations. */
482 } else {
483 UChar** p;
484 Int r = loadquery(L_GETMESSAGES, buf, NBUF);
485 VG_(debugLog)(0, "initimg", "loadquery returned %d (0 = success)\n", r);
486 p = (UChar**)(&buf[0]);
487 for (; *p; p++)
488 VG_(debugLog)(0, "initimg", "\"%s\"\n", *p);
489 VG_(debugLog)(0, "initimg", "Use /usr/sbin/execerror to make "
490 "sense of above string(s)\n");
491 VG_(debugLog)(0, "initimg", "See also comments at the bottom of\n");
492 VG_(debugLog)(0, "initimg", "coregrind/m_initimg/"
493 "initimg-aix5.c (in Valgrind sources)\n");
494 }
495# undef NBUF
496}
497
498/* Take the strings that this prints out and feed them
499 to /usr/sbin/execerror. For example, it might print
500
501 (ld 3 1 __libc_freeres /foo/bar/ppc32-aix5/vgpreload_core.so
502
503 in which case
504
505 $ execerror xyzzy \
506 "(ld 3 1 __libc_freeres /foo/bar/ppc32-aix5/vgpreload_core.so"
507
508 gets you
509
510 Could not load program xyzzy:
511 rtld: 0712-001 Symbol __libc_freeres was referenced
512 from module /foo/bar/ppc32-aix5/vgpreload_core.so(),
513 but a runtime definition
514 of the symbol was not found.
515*/
516
517/*--------------------------------------------------------------------*/
518/*--- initimg-aix5.c ---*/
519/*--------------------------------------------------------------------*/