~bkerensa/ubuntu/raring/valgrind/merge-from-deb

« back to all changes in this revision

Viewing changes to coregrind/m_translate.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrés Roldán
  • Date: 2008-06-13 02:31:40 UTC
  • mto: (1.4.1 upstream) (2.2.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: james.westby@ubuntu.com-20080613023140-iwk33rz9rhvfkr96
Import upstream version 3.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
   This file is part of Valgrind, a dynamic binary instrumentation
9
9
   framework.
10
10
 
11
 
   Copyright (C) 2000-2006 Julian Seward 
 
11
   Copyright (C) 2000-2007 Julian Seward 
12
12
      jseward@acm.org
13
13
 
14
14
   This program is free software; you can redistribute it and/or
30
30
*/
31
31
 
32
32
#include "pub_core_basics.h"
 
33
#include "pub_core_vki.h"
33
34
#include "pub_core_aspacemgr.h"
34
35
 
35
36
#include "pub_core_machine.h"    // VG_(fnptr_to_fnentry)
53
54
                               // VG_(run_a_noredir_translation__return_point)
54
55
 
55
56
#include "pub_core_threadstate.h"  // VexGuestArchState
56
 
#include "pub_core_trampoline.h"   // VG_(ppc64_linux_magic_redirect_return_stub)
 
57
#include "pub_core_trampoline.h"   // VG_(ppctoc_magic_redirect_return_stub)
57
58
 
58
59
 
59
60
/*------------------------------------------------------------*/
205
206
   If all the changes to SP leading up to a PUT(SP) are by known, small
206
207
   constants, we can do a specific call to eg. new_mem_stack_4, otherwise
207
208
   we fall back to the case that handles an unknown SP change.
 
209
 
 
210
   There is some extra complexity to deal correctly with updates to
 
211
   only parts of SP.  Bizarre, but it has been known to happen.
208
212
*/
209
213
static
210
 
IRBB* vg_SP_update_pass ( void*             closureV,
211
 
                          IRBB*             bb_in, 
 
214
IRSB* vg_SP_update_pass ( void*             closureV,
 
215
                          IRSB*             sb_in, 
212
216
                          VexGuestLayout*   layout, 
213
217
                          VexGuestExtents*  vge,
214
218
                          IRType            gWordTy, 
215
219
                          IRType            hWordTy )
216
220
{
217
 
   Int      i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
218
 
   IRDirty  *dcall, *d;
219
 
   IRStmt*  st;
220
 
   IRExpr*  e;
221
 
   IRArray* descr;
222
 
   IRType   typeof_SP;
223
 
   Long     delta, con;
 
221
   Int         i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
 
222
   Int         first_SP, last_SP, first_Put, last_Put;
 
223
   IRDirty     *dcall, *d;
 
224
   IRStmt*     st;
 
225
   IRExpr*     e;
 
226
   IRRegArray* descr;
 
227
   IRType      typeof_SP;
 
228
   Long        delta, con;
224
229
 
225
230
   /* Set up BB */
226
 
   IRBB* bb     = emptyIRBB();
227
 
   bb->tyenv    = dopyIRTypeEnv(bb_in->tyenv);
228
 
   bb->next     = dopyIRExpr(bb_in->next);
229
 
   bb->jumpkind = bb_in->jumpkind;
 
231
   IRSB* bb     = emptyIRSB();
 
232
   bb->tyenv    = deepCopyIRTypeEnv(sb_in->tyenv);
 
233
   bb->next     = deepCopyIRExpr(sb_in->next);
 
234
   bb->jumpkind = sb_in->jumpkind;
230
235
 
231
236
   delta = 0;
232
237
 
257
262
                    "track_" #kind "_mem_stack_" #syze,                 \
258
263
                    VG_(fnptr_to_fnentry)(                              \
259
264
                       VG_(tdict).track_##kind##_mem_stack_##syze ),    \
260
 
                    mkIRExprVec_1(IRExpr_Tmp(tmpp))                     \
 
265
                    mkIRExprVec_1(IRExpr_RdTmp(tmpp))                   \
261
266
                 );                                                     \
262
267
         dcall->nFxState = 1;                                           \
263
268
         dcall->fxState[0].fx     = Ifx_Read;                           \
264
269
         dcall->fxState[0].offset = layout->offset_SP;                  \
265
270
         dcall->fxState[0].size   = layout->sizeof_SP;                  \
266
271
                                                                        \
267
 
         addStmtToIRBB( bb, IRStmt_Dirty(dcall) );                      \
 
272
         addStmtToIRSB( bb, IRStmt_Dirty(dcall) );                      \
268
273
                                                                        \
269
274
         update_SP_aliases(-delta);                                     \
270
275
                                                                        \
274
279
 
275
280
   clear_SP_aliases();
276
281
 
277
 
   for (i = 0; i <  bb_in->stmts_used; i++) {
 
282
   for (i = 0; i <  sb_in->stmts_used; i++) {
278
283
 
279
 
      st = bb_in->stmts[i];
 
284
      st = sb_in->stmts[i];
280
285
 
281
286
      /* t = Get(sp):   curr = t, delta = 0 */
282
 
      if (st->tag != Ist_Tmp) goto case2;
283
 
      e = st->Ist.Tmp.data;
 
287
      if (st->tag != Ist_WrTmp) goto case2;
 
288
      e = st->Ist.WrTmp.data;
284
289
      if (e->tag != Iex_Get)              goto case2;
285
290
      if (e->Iex.Get.offset != offset_SP) goto case2;
286
291
      if (e->Iex.Get.ty != typeof_SP)     goto case2;
287
 
      add_SP_alias(st->Ist.Tmp.tmp, 0);
288
 
      addStmtToIRBB( bb, st );
 
292
      vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
 
293
      add_SP_alias(st->Ist.WrTmp.tmp, 0);
 
294
      addStmtToIRSB( bb, st );
289
295
      continue;
290
296
 
291
297
     case2:
292
298
      /* t' = curr +/- const:   curr = t',  delta +=/-= const */
293
 
      if (st->tag != Ist_Tmp) goto case3;
294
 
      e = st->Ist.Tmp.data;
 
299
      if (st->tag != Ist_WrTmp) goto case3;
 
300
      e = st->Ist.WrTmp.data;
295
301
      if (e->tag != Iex_Binop) goto case3;
296
 
      if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
297
 
      if (!get_SP_delta(e->Iex.Binop.arg1->Iex.Tmp.tmp, &delta)) goto case3;
 
302
      if (e->Iex.Binop.arg1->tag != Iex_RdTmp) goto case3;
 
303
      if (!get_SP_delta(e->Iex.Binop.arg1->Iex.RdTmp.tmp, &delta)) goto case3;
298
304
      if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
299
305
      if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
300
306
      con = GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
 
307
      vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
301
308
      if (IS_ADD(e->Iex.Binop.op)) {
302
 
         add_SP_alias(st->Ist.Tmp.tmp, delta + con);
 
309
         add_SP_alias(st->Ist.WrTmp.tmp, delta + con);
303
310
      } else {
304
 
         add_SP_alias(st->Ist.Tmp.tmp, delta - con);
 
311
         add_SP_alias(st->Ist.WrTmp.tmp, delta - con);
305
312
      }
306
 
      addStmtToIRBB( bb, st );
 
313
      addStmtToIRSB( bb, st );
307
314
      continue;
308
315
 
309
316
     case3:
310
317
      /* t' = curr:   curr = t' */
311
 
      if (st->tag != Ist_Tmp) goto case4;
312
 
      e = st->Ist.Tmp.data;
313
 
      if (e->tag != Iex_Tmp) goto case4;
314
 
      if (!get_SP_delta(e->Iex.Tmp.tmp, &delta)) goto case4;
315
 
      add_SP_alias(st->Ist.Tmp.tmp, delta);
316
 
      addStmtToIRBB( bb, st );
 
318
      if (st->tag != Ist_WrTmp) goto case4;
 
319
      e = st->Ist.WrTmp.data;
 
320
      if (e->tag != Iex_RdTmp) goto case4;
 
321
      if (!get_SP_delta(e->Iex.RdTmp.tmp, &delta)) goto case4;
 
322
      vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
 
323
      add_SP_alias(st->Ist.WrTmp.tmp, delta);
 
324
      addStmtToIRSB( bb, st );
317
325
      continue;
318
326
 
319
327
     case4:
320
328
      /* Put(sp) = curr */
 
329
      /* More generally, we must correctly handle a Put which writes
 
330
         any part of SP, not just the case where all of SP is
 
331
         written. */
321
332
      if (st->tag != Ist_Put) goto case5;
322
 
      if (st->Ist.Put.offset != offset_SP) goto case5;
323
 
      if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
324
 
      if (get_SP_delta(st->Ist.Put.data->Iex.Tmp.tmp, &delta)) {
325
 
         IRTemp tttmp = st->Ist.Put.data->Iex.Tmp.tmp;
 
333
      first_SP  = offset_SP;
 
334
      last_SP   = first_SP + sizeof_SP - 1;
 
335
      first_Put = st->Ist.Put.offset;
 
336
      last_Put  = first_Put
 
337
                  + sizeofIRType( typeOfIRExpr( bb->tyenv, st->Ist.Put.data ))
 
338
                  - 1;
 
339
      vg_assert(first_SP <= last_SP);
 
340
      vg_assert(first_Put <= last_Put);
 
341
 
 
342
      if (last_Put < first_SP || last_SP < first_Put)
 
343
         goto case5; /* no overlap */
 
344
 
 
345
      if (st->Ist.Put.data->tag == Iex_RdTmp
 
346
          && get_SP_delta(st->Ist.Put.data->Iex.RdTmp.tmp, &delta)) {
 
347
         IRTemp tttmp = st->Ist.Put.data->Iex.RdTmp.tmp;
 
348
         /* Why should the following assertion hold?  Because any
 
349
            alias added by put_SP_alias must be of a temporary which
 
350
            has the same type as typeof_SP, and whose value is a Get
 
351
            at exactly offset_SP of size typeof_SP.  Each call to
 
352
            put_SP_alias is immediately preceded by an assertion that
 
353
            we are putting in a binding for a correctly-typed
 
354
            temporary. */
 
355
         vg_assert( typeOfIRTemp(bb->tyenv, tttmp) == typeof_SP );
 
356
         /* From the same type-and-offset-correctness argument, if 
 
357
            we found a useable alias, it must for an "exact" write of SP. */
 
358
         vg_assert(first_SP == first_Put);
 
359
         vg_assert(last_SP == last_Put);
326
360
         switch (delta) {
327
 
            case    0:                      addStmtToIRBB(bb,st); continue;
328
 
            case    4: DO(die,  4,  tttmp); addStmtToIRBB(bb,st); continue;
329
 
            case   -4: DO(new,  4,  tttmp); addStmtToIRBB(bb,st); continue;
330
 
            case    8: DO(die,  8,  tttmp); addStmtToIRBB(bb,st); continue;
331
 
            case   -8: DO(new,  8,  tttmp); addStmtToIRBB(bb,st); continue;
332
 
            case   12: DO(die,  12, tttmp); addStmtToIRBB(bb,st); continue;
333
 
            case  -12: DO(new,  12, tttmp); addStmtToIRBB(bb,st); continue;
334
 
            case   16: DO(die,  16, tttmp); addStmtToIRBB(bb,st); continue;
335
 
            case  -16: DO(new,  16, tttmp); addStmtToIRBB(bb,st); continue;
336
 
            case   32: DO(die,  32, tttmp); addStmtToIRBB(bb,st); continue;
337
 
            case  -32: DO(new,  32, tttmp); addStmtToIRBB(bb,st); continue;
338
 
            case  112: DO(die, 112, tttmp); addStmtToIRBB(bb,st); continue;
339
 
            case -112: DO(new, 112, tttmp); addStmtToIRBB(bb,st); continue;
340
 
            case  128: DO(die, 128, tttmp); addStmtToIRBB(bb,st); continue;
341
 
            case -128: DO(new, 128, tttmp); addStmtToIRBB(bb,st); continue;
342
 
            case  144: DO(die, 144, tttmp); addStmtToIRBB(bb,st); continue;
343
 
            case -144: DO(new, 144, tttmp); addStmtToIRBB(bb,st); continue;
344
 
            case  160: DO(die, 160, tttmp); addStmtToIRBB(bb,st); continue;
345
 
            case -160: DO(new, 160, tttmp); addStmtToIRBB(bb,st); continue;
 
361
            case    0:                      addStmtToIRSB(bb,st); continue;
 
362
            case    4: DO(die,  4,  tttmp); addStmtToIRSB(bb,st); continue;
 
363
            case   -4: DO(new,  4,  tttmp); addStmtToIRSB(bb,st); continue;
 
364
            case    8: DO(die,  8,  tttmp); addStmtToIRSB(bb,st); continue;
 
365
            case   -8: DO(new,  8,  tttmp); addStmtToIRSB(bb,st); continue;
 
366
            case   12: DO(die,  12, tttmp); addStmtToIRSB(bb,st); continue;
 
367
            case  -12: DO(new,  12, tttmp); addStmtToIRSB(bb,st); continue;
 
368
            case   16: DO(die,  16, tttmp); addStmtToIRSB(bb,st); continue;
 
369
            case  -16: DO(new,  16, tttmp); addStmtToIRSB(bb,st); continue;
 
370
            case   32: DO(die,  32, tttmp); addStmtToIRSB(bb,st); continue;
 
371
            case  -32: DO(new,  32, tttmp); addStmtToIRSB(bb,st); continue;
 
372
            case  112: DO(die, 112, tttmp); addStmtToIRSB(bb,st); continue;
 
373
            case -112: DO(new, 112, tttmp); addStmtToIRSB(bb,st); continue;
 
374
            case  128: DO(die, 128, tttmp); addStmtToIRSB(bb,st); continue;
 
375
            case -128: DO(new, 128, tttmp); addStmtToIRSB(bb,st); continue;
 
376
            case  144: DO(die, 144, tttmp); addStmtToIRSB(bb,st); continue;
 
377
            case -144: DO(new, 144, tttmp); addStmtToIRSB(bb,st); continue;
 
378
            case  160: DO(die, 160, tttmp); addStmtToIRSB(bb,st); continue;
 
379
            case -160: DO(new, 160, tttmp); addStmtToIRSB(bb,st); continue;
346
380
            default:  
347
381
               /* common values for ppc64: 144 128 160 112 176 */
348
382
               n_SP_updates_generic_known++;
349
383
               goto generic;
350
384
         }
351
385
      } else {
 
386
         /* Deal with an unknown update to SP.  We're here because
 
387
            either:
 
388
            (1) the Put does not exactly cover SP; it is a partial update.
 
389
                Highly unlikely, but has been known to happen for 16-bit
 
390
                Windows apps running on Wine, doing 16-bit adjustments to
 
391
                %sp.
 
392
            (2) the Put does exactly cover SP, but we are unable to
 
393
                determine how the value relates to the old SP.  In any 
 
394
                case, we cannot assume that the Put.data value is a tmp;
 
395
                we must assume it can be anything allowed in flat IR (tmp
 
396
                or const).
 
397
         */
352
398
         IRTemp old_SP;
353
399
         n_SP_updates_generic_unknown++;
354
400
 
358
404
        generic:
359
405
         /* Pass both the old and new SP values to this helper. */
360
406
         old_SP = newIRTemp(bb->tyenv, typeof_SP);
361
 
         addStmtToIRBB( 
 
407
         addStmtToIRSB( 
362
408
            bb,
363
 
            IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) ) 
 
409
            IRStmt_WrTmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) ) 
364
410
         );
365
411
 
366
 
         dcall = unsafeIRDirty_0_N( 
367
 
                    2/*regparms*/, 
368
 
                    "VG_(unknown_SP_update)", 
369
 
                    VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
370
 
                    mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data ) 
371
 
                 );
372
 
         addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
373
 
 
374
 
         addStmtToIRBB( bb, st );
375
 
 
 
412
         /* Now we know what the old value of SP is.  But knowing the new
 
413
            value is a bit tricky if there is a partial write. */
 
414
         if (first_Put == first_SP && last_Put == last_SP) {
 
415
           /* The common case, an exact write to SP.  So st->Ist.Put.data
 
416
              does hold the new value; simple. */
 
417
            dcall = unsafeIRDirty_0_N( 
 
418
                       2/*regparms*/, 
 
419
                       "VG_(unknown_SP_update)", 
 
420
                       VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
 
421
                       mkIRExprVec_2( IRExpr_RdTmp(old_SP), st->Ist.Put.data ) 
 
422
                    );
 
423
            addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
 
424
            /* don't forget the original assignment */
 
425
            addStmtToIRSB( bb, st );
 
426
         } else {
 
427
            /* We have a partial update to SP.  We need to know what
 
428
               the new SP will be, and hand that to the helper call,
 
429
               but when the helper call happens, SP must hold the
 
430
               value it had before the update.  Tricky.
 
431
               Therefore use the following kludge:
 
432
               1. do the partial SP update (Put)
 
433
               2. Get the new SP value into a tmp, new_SP
 
434
               3. Put old_SP
 
435
               4. Call the helper
 
436
               5. Put new_SP
 
437
            */
 
438
            IRTemp new_SP;
 
439
            /* 1 */
 
440
            addStmtToIRSB( bb, st );
 
441
            /* 2 */
 
442
            new_SP = newIRTemp(bb->tyenv, typeof_SP);
 
443
            addStmtToIRSB( 
 
444
               bb,
 
445
               IRStmt_WrTmp( new_SP, IRExpr_Get(offset_SP, typeof_SP) ) 
 
446
            );
 
447
            /* 3 */
 
448
            addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(old_SP) ));
 
449
            /* 4 */
 
450
            dcall = unsafeIRDirty_0_N( 
 
451
                       2/*regparms*/, 
 
452
                       "VG_(unknown_SP_update)", 
 
453
                       VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
 
454
                       mkIRExprVec_2( IRExpr_RdTmp(old_SP),
 
455
                                      IRExpr_RdTmp(new_SP))
 
456
                    );
 
457
            addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
 
458
            /* 5 */
 
459
            addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(new_SP) ));
 
460
         }
 
461
 
 
462
         /* Forget what we already know. */
376
463
         clear_SP_aliases();
377
 
         add_SP_alias(st->Ist.Put.data->Iex.Tmp.tmp, 0);
 
464
 
 
465
         /* If this is a Put of a tmp that exactly updates SP,
 
466
            start tracking aliases against this tmp. */
 
467
 
 
468
         if (first_Put == first_SP && last_Put == last_SP
 
469
             && st->Ist.Put.data->tag == Iex_RdTmp) {
 
470
            vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.Put.data->Iex.RdTmp.tmp)
 
471
                       == typeof_SP );
 
472
            add_SP_alias(st->Ist.Put.data->Iex.RdTmp.tmp, 0);
 
473
         }
378
474
         continue;
379
475
      }
380
476
 
385
481
      if (st->tag == Ist_PutI) {
386
482
         descr = st->Ist.PutI.descr;
387
483
         minoff_ST = descr->base;
388
 
         maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
389
 
         if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
 
484
         maxoff_ST = descr->base 
 
485
                     + descr->nElems * sizeofIRType(descr->elemTy) - 1;
 
486
         if (!(offset_SP > maxoff_ST
 
487
               || (offset_SP + sizeof_SP - 1) < minoff_ST))
390
488
            goto complain;
391
489
      }
392
490
      if (st->tag == Ist_Dirty) {
396
494
            maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
397
495
            if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
398
496
               continue;
399
 
            if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
 
497
            if (!(offset_SP > maxoff_ST
 
498
                  || (offset_SP + sizeof_SP - 1) < minoff_ST))
400
499
               goto complain;
401
500
         }
402
501
      }
403
502
 
404
503
      /* well, not interesting.  Just copy and keep going. */
405
 
      addStmtToIRBB( bb, st );
 
504
      addStmtToIRSB( bb, st );
406
505
 
407
 
   } /* for (i = 0; i <  bb_in->stmts_used; i++) */
 
506
   } /* for (i = 0; i < sb_in->stmts_used; i++) */
408
507
 
409
508
   return bb;
410
509
 
473
572
 
474
573
/* Vex dumps the final code in here.  Then we can copy it off
475
574
   wherever we like. */
476
 
#define N_TMPBUF 20000
 
575
/* 60000: should agree with assertion in VG_(add_to_transtab) in
 
576
   m_transtab.c. */
 
577
#define N_TMPBUF 60000
477
578
static UChar tmpbuf[N_TMPBUF];
478
579
 
479
580
 
503
604
/* Look for reasons to disallow making translations from the given
504
605
   segment. */
505
606
 
506
 
static Bool translations_allowable_from_seg ( NSegment* seg )
 
607
static Bool translations_allowable_from_seg ( NSegment const* seg )
507
608
{
508
609
#  if defined(VGA_x86)
509
610
   Bool allowR = True;
519
620
/* Is a self-check required for a translation of a guest address
520
621
   inside segment SEG when requested by thread TID ? */
521
622
 
522
 
static Bool self_check_required ( NSegment* seg, ThreadId tid )
 
623
static Bool self_check_required ( NSegment const* seg, ThreadId tid )
523
624
{
524
625
   switch (VG_(clo_smc_check)) {
525
626
      case Vg_SmcNone:  return False;
547
648
static Bool chase_into_ok ( void* closureV, Addr64 addr64 )
548
649
{
549
650
   Addr               addr    = (Addr)addr64;
550
 
   NSegment*          seg     = VG_(am_find_nsegment)(addr);
 
651
   NSegment const*    seg     = VG_(am_find_nsegment)(addr);
551
652
   VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
552
653
 
553
654
   /* Work through a list of possibilities why we might not want to
565
666
   if (addr != VG_(redir_do_lookup)(addr, NULL))
566
667
      goto dontchase;
567
668
 
568
 
#  if defined(VGP_ppc64_linux)
569
 
   /* This needs to be at the start of its own block.  Don't chase. */
570
 
   if (addr64 == (Addr64)&VG_(ppc64_linux_magic_redirect_return_stub))
 
669
#  if defined(VG_PLAT_USES_PPCTOC)
 
670
   /* This needs to be at the start of its own block.  Don't chase. Re
 
671
      ULong_to_Ptr, be careful to ensure we only compare 32 bits on a
 
672
      32-bit target.*/
 
673
   if (ULong_to_Ptr(addr64)
 
674
       == (void*)&VG_(ppctoc_magic_redirect_return_stub))
571
675
      goto dontchase;
572
676
#  endif
573
677
 
 
678
   /* overly conservative, but .. don't chase into the distinguished
 
679
      address that m_transtab uses as an empty-slot marker for
 
680
      VG_(tt_fast). */
 
681
   if (addr == TRANSTAB_BOGUS_GUEST_ADDR)
 
682
      goto dontchase;
 
683
 
574
684
   /* well, ok then.  go on and chase. */
575
685
   return True;
576
686
 
578
688
   /*NOTREACHED*/
579
689
 
580
690
  dontchase:
581
 
   if (0) VG_(printf)("not chasing into 0x%x\n", addr);
 
691
   if (0) VG_(printf)("not chasing into 0x%lx\n", addr);
582
692
   return False;
583
693
}
584
694
 
585
695
 
586
 
/* --------------- ppc64-linux specific helpers --------------- */
 
696
/* --------------- helpers for with-TOC platforms --------------- */
 
697
 
 
698
/* NOTE: with-TOC platforms are: ppc64-linux, ppc32-aix5, ppc64-aix5. */
587
699
 
588
700
static IRExpr* mkU64 ( ULong n ) {
589
701
   return IRExpr_Const(IRConst_U64(n));
591
703
static IRExpr* mkU32 ( UInt n ) {
592
704
   return IRExpr_Const(IRConst_U32(n));
593
705
}
594
 
#if defined(VGP_ppc64_linux)
 
706
 
 
707
#if defined(VG_PLAT_USES_PPCTOC)
595
708
static IRExpr* mkU8 ( UChar n ) {
596
709
   return IRExpr_Const(IRConst_U8(n));
597
710
}
598
 
 
599
 
static void gen_PUSH ( IRBB* bb, IRExpr* e )
 
711
static IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) {
 
712
   if (typeOfIRExpr(tyenv, e) == Ity_I32) {
 
713
      return e;
 
714
   } else {
 
715
      vg_assert(typeOfIRExpr(tyenv, e) == Ity_I64);
 
716
      return IRExpr_Unop(Iop_64to32, e);
 
717
   }
 
718
}
 
719
 
 
720
/* Generate code to push word-typed expression 'e' onto this thread's
 
721
   redir stack, checking for stack overflow and generating code to
 
722
   bomb out if so. */
 
723
 
 
724
static void gen_PUSH ( IRSB* bb, IRExpr* e )
600
725
{
601
 
   Int stack_size       = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
602
 
   Int offB_REDIR_SP    = offsetof(VexGuestPPC64State,guest_REDIR_SP);
603
 
   Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
604
 
   Int offB_EMWARN      = offsetof(VexGuestPPC64State,guest_EMWARN);
605
 
 
606
 
   IRArray* descr = mkIRArray( offB_REDIR_STACK, Ity_I64, stack_size );
607
 
   IRTemp   t1    = newIRTemp( bb->tyenv, Ity_I64 );
608
 
   IRExpr*  one   = mkU64(1);
 
726
   IRRegArray* descr;
 
727
   IRTemp      t1;
 
728
   IRExpr*     one;
 
729
 
 
730
#  if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
 
731
   Int    stack_size       = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
 
732
   Int    offB_REDIR_SP    = offsetof(VexGuestPPC64State,guest_REDIR_SP);
 
733
   Int    offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
 
734
   Int    offB_EMWARN      = offsetof(VexGuestPPC64State,guest_EMWARN);
 
735
   Bool   is64             = True;
 
736
   IRType ty_Word          = Ity_I64;
 
737
   IROp   op_CmpNE         = Iop_CmpNE64;
 
738
   IROp   op_Sar           = Iop_Sar64;
 
739
   IROp   op_Sub           = Iop_Sub64;
 
740
   IROp   op_Add           = Iop_Add64;
 
741
   IRExpr*(*mkU)(ULong)    = mkU64;
 
742
   vg_assert(VG_WORDSIZE == 8);
 
743
#  else
 
744
   Int    stack_size       = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
 
745
   Int    offB_REDIR_SP    = offsetof(VexGuestPPC32State,guest_REDIR_SP);
 
746
   Int    offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
 
747
   Int    offB_EMWARN      = offsetof(VexGuestPPC32State,guest_EMWARN);
 
748
   Bool   is64             = False;
 
749
   IRType ty_Word          = Ity_I32;
 
750
   IROp   op_CmpNE         = Iop_CmpNE32;
 
751
   IROp   op_Sar           = Iop_Sar32;
 
752
   IROp   op_Sub           = Iop_Sub32;
 
753
   IROp   op_Add           = Iop_Add32;
 
754
   IRExpr*(*mkU)(UInt)     = mkU32;
 
755
   vg_assert(VG_WORDSIZE == 4);
 
756
#  endif
 
757
 
 
758
   vg_assert(sizeof(void*) == VG_WORDSIZE);
 
759
   vg_assert(sizeof(Word)  == VG_WORDSIZE);
 
760
   vg_assert(sizeof(Addr)  == VG_WORDSIZE);
 
761
 
 
762
   descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
 
763
   t1    = newIRTemp( bb->tyenv, ty_Word );
 
764
   one   = mkU(1);
 
765
 
 
766
   vg_assert(typeOfIRExpr(bb->tyenv, e) == ty_Word);
609
767
 
610
768
   /* t1 = guest_REDIR_SP + 1 */
611
 
   addStmtToIRBB(
 
769
   addStmtToIRSB(
612
770
      bb, 
613
 
      IRStmt_Tmp(
 
771
      IRStmt_WrTmp(
614
772
         t1, 
615
 
         IRExpr_Binop(Iop_Add64, IRExpr_Get( offB_REDIR_SP, Ity_I64 ), one)
 
773
         IRExpr_Binop(op_Add, IRExpr_Get( offB_REDIR_SP, ty_Word ), one)
616
774
      )
617
775
   );
618
776
 
621
779
      this is an unrecoverable error and will lead to Valgrind
622
780
      shutting down.  _EMWARN is set regardless - that's harmless
623
781
      since is only has a meaning if the exit is taken. */
624
 
   addStmtToIRBB(
 
782
   addStmtToIRSB(
625
783
      bb,
626
784
      IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_overflow))
627
785
   );
628
 
   addStmtToIRBB(
 
786
   addStmtToIRSB(
629
787
      bb,
630
788
      IRStmt_Exit(
631
789
         IRExpr_Binop(
632
 
            Iop_CmpNE64,
 
790
            op_CmpNE,
633
791
            IRExpr_Binop(
634
 
               Iop_Sar64,
635
 
               IRExpr_Binop(Iop_Sub64,mkU64(stack_size-1),IRExpr_Tmp(t1)),
636
 
               mkU8(63)
 
792
               op_Sar,
 
793
               IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_RdTmp(t1)),
 
794
               mkU8(8 * VG_WORDSIZE - 1)
637
795
            ),
638
 
            mkU64(0)
 
796
            mkU(0)
639
797
         ),
640
798
         Ijk_EmFail,
641
 
         IRConst_U64(0)
 
799
         is64 ? IRConst_U64(0) : IRConst_U32(0)
642
800
      )
643
801
   );
644
802
 
645
803
   /* guest_REDIR_SP = t1 */
646
 
   addStmtToIRBB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_Tmp(t1)));
 
804
   addStmtToIRSB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_RdTmp(t1)));
647
805
 
648
806
   /* guest_REDIR_STACK[t1+0] = e */
649
 
   addStmtToIRBB(
 
807
   /* PutI/GetI have I32-typed indexes regardless of guest word size */
 
808
   addStmtToIRSB(
650
809
      bb, 
651
 
      IRStmt_PutI(descr, IRExpr_Unop(Iop_64to32,IRExpr_Tmp(t1)), 0, e)
 
810
      IRStmt_PutI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0, e)
652
811
   );
653
812
}
654
813
 
655
 
static IRTemp gen_POP ( IRBB* bb )
 
814
 
 
815
/* Generate code to pop a word-sized value from this thread's redir
 
816
   stack, binding it to a new temporary, which is returned.  As with
 
817
   gen_PUSH, an overflow check is also performed. */
 
818
 
 
819
static IRTemp gen_POP ( IRSB* bb )
656
820
{
657
 
   Int stack_size       = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
658
 
   Int offB_REDIR_SP    = offsetof(VexGuestPPC64State,guest_REDIR_SP);
659
 
   Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
660
 
   Int offB_EMWARN      = offsetof(VexGuestPPC64State,guest_EMWARN);
661
 
 
662
 
   IRArray* descr = mkIRArray( offB_REDIR_STACK, Ity_I64, stack_size );
663
 
   IRTemp   t1    = newIRTemp( bb->tyenv, Ity_I64 );
664
 
   IRTemp   res   = newIRTemp( bb->tyenv, Ity_I64 );
665
 
   IRExpr*  one   = mkU64(1);
 
821
#  if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
 
822
   Int    stack_size       = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
 
823
   Int    offB_REDIR_SP    = offsetof(VexGuestPPC64State,guest_REDIR_SP);
 
824
   Int    offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
 
825
   Int    offB_EMWARN      = offsetof(VexGuestPPC64State,guest_EMWARN);
 
826
   Bool   is64             = True;
 
827
   IRType ty_Word          = Ity_I64;
 
828
   IROp   op_CmpNE         = Iop_CmpNE64;
 
829
   IROp   op_Sar           = Iop_Sar64;
 
830
   IROp   op_Sub           = Iop_Sub64;
 
831
   IRExpr*(*mkU)(ULong)    = mkU64;
 
832
#  else
 
833
   Int    stack_size       = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
 
834
   Int    offB_REDIR_SP    = offsetof(VexGuestPPC32State,guest_REDIR_SP);
 
835
   Int    offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
 
836
   Int    offB_EMWARN      = offsetof(VexGuestPPC32State,guest_EMWARN);
 
837
   Bool   is64             = False;
 
838
   IRType ty_Word          = Ity_I32;
 
839
   IROp   op_CmpNE         = Iop_CmpNE32;
 
840
   IROp   op_Sar           = Iop_Sar32;
 
841
   IROp   op_Sub           = Iop_Sub32;
 
842
   IRExpr*(*mkU)(UInt)     = mkU32;
 
843
#  endif
 
844
 
 
845
   IRRegArray* descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
 
846
   IRTemp      t1    = newIRTemp( bb->tyenv, ty_Word );
 
847
   IRTemp      res   = newIRTemp( bb->tyenv, ty_Word );
 
848
   IRExpr*     one   = mkU(1);
 
849
 
 
850
   vg_assert(sizeof(void*) == VG_WORDSIZE);
 
851
   vg_assert(sizeof(Word)  == VG_WORDSIZE);
 
852
   vg_assert(sizeof(Addr)  == VG_WORDSIZE);
666
853
 
667
854
   /* t1 = guest_REDIR_SP */
668
 
   addStmtToIRBB(
 
855
   addStmtToIRSB(
669
856
      bb, 
670
 
      IRStmt_Tmp( t1, IRExpr_Get( offB_REDIR_SP, Ity_I64 ) )
 
857
      IRStmt_WrTmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) )
671
858
   );
672
859
 
673
860
   /* Bomb out if t1 < 0.  Same comments as gen_PUSH apply. */
674
 
   addStmtToIRBB(
 
861
   addStmtToIRSB(
675
862
      bb,
676
863
      IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_underflow))
677
864
   );
678
 
   addStmtToIRBB(
 
865
   addStmtToIRSB(
679
866
      bb,
680
867
      IRStmt_Exit(
681
868
         IRExpr_Binop(
682
 
            Iop_CmpNE64,
 
869
            op_CmpNE,
683
870
            IRExpr_Binop(
684
 
               Iop_Sar64,
685
 
               IRExpr_Tmp(t1),
686
 
               mkU8(63)
 
871
               op_Sar,
 
872
               IRExpr_RdTmp(t1),
 
873
               mkU8(8 * VG_WORDSIZE - 1)
687
874
            ),
688
 
            mkU64(0)
 
875
            mkU(0)
689
876
         ),
690
877
         Ijk_EmFail,
691
 
         IRConst_U64(0)
 
878
         is64 ? IRConst_U64(0) : IRConst_U32(0)
692
879
      )
693
880
   );
694
881
 
695
882
   /* res = guest_REDIR_STACK[t1+0] */
696
 
   addStmtToIRBB(
 
883
   /* PutI/GetI have I32-typed indexes regardless of guest word size */
 
884
   addStmtToIRSB(
697
885
      bb,
698
 
      IRStmt_Tmp(
 
886
      IRStmt_WrTmp(
699
887
         res, 
700
 
         IRExpr_GetI(descr, IRExpr_Unop(Iop_64to32,IRExpr_Tmp(t1)), 0)
 
888
         IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0)
701
889
      )
702
890
   );
703
891
 
704
892
   /* guest_REDIR_SP = t1-1 */
705
 
   addStmtToIRBB(
 
893
   addStmtToIRSB(
706
894
      bb, 
707
 
      IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(Iop_Sub64, IRExpr_Tmp(t1), one))
 
895
      IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(op_Sub, IRExpr_RdTmp(t1), one))
708
896
   );
709
897
 
710
898
   return res;
711
899
}
712
900
 
713
 
static void gen_push_and_set_LR_R2 ( IRBB* bb, Addr64 new_R2_value )
 
901
/* Generate code to push LR and R2 onto this thread's redir stack,
 
902
   then set R2 to the new value (which is the TOC pointer to be used
 
903
   for the duration of the replacement function, as determined by
 
904
   m_debuginfo), and set LR to the magic return stub, so we get to
 
905
   intercept the return and restore R2 and L2 to the values saved
 
906
   here. */
 
907
 
 
908
static void gen_push_and_set_LR_R2 ( IRSB* bb, Addr64 new_R2_value )
714
909
{
715
 
   Addr64 bogus_RA = (Addr64)&VG_(ppc64_linux_magic_redirect_return_stub);
716
 
   Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
717
 
   Int offB_LR   = offsetof(VexGuestPPC64State,guest_LR);
 
910
#  if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
 
911
   Addr64 bogus_RA  = (Addr64)&VG_(ppctoc_magic_redirect_return_stub);
 
912
   Int    offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
 
913
   Int    offB_LR   = offsetof(VexGuestPPC64State,guest_LR);
718
914
   gen_PUSH( bb, IRExpr_Get(offB_LR,   Ity_I64) );
719
915
   gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
720
 
   addStmtToIRBB( bb, IRStmt_Put( offB_LR,   mkU64( bogus_RA )) );
721
 
   addStmtToIRBB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) );
 
916
   addStmtToIRSB( bb, IRStmt_Put( offB_LR,   mkU64( bogus_RA )) );
 
917
   addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) );
 
918
 
 
919
#  elif defined(VGP_ppc32_aix5)
 
920
   Addr32 bogus_RA  = (Addr32)&VG_(ppctoc_magic_redirect_return_stub);
 
921
   Int    offB_GPR2 = offsetof(VexGuestPPC32State,guest_GPR2);
 
922
   Int    offB_LR   = offsetof(VexGuestPPC32State,guest_LR);
 
923
   gen_PUSH( bb, IRExpr_Get(offB_LR,   Ity_I32) );
 
924
   gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I32) );
 
925
   addStmtToIRSB( bb, IRStmt_Put( offB_LR,   mkU32( bogus_RA )) );
 
926
   addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU32( new_R2_value )) );
 
927
 
 
928
#  else
 
929
#    error Platform is not TOC-afflicted, fortunately
 
930
#  endif
722
931
}
723
932
 
724
 
static void gen_pop_R2_LR_then_bLR ( IRBB* bb )
 
933
static void gen_pop_R2_LR_then_bLR ( IRSB* bb )
725
934
{
726
 
   Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
727
 
   Int offB_LR   = offsetof(VexGuestPPC64State,guest_LR);
728
 
   IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I64 );
729
 
   IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I64 );
730
 
   /* Restore R2 */
731
 
   old_R2 = gen_POP( bb );
732
 
   addStmtToIRBB( bb, IRStmt_Put( offB_GPR2, IRExpr_Tmp(old_R2)) );
733
 
   /* Restore LR */
734
 
   old_LR = gen_POP( bb );
735
 
   addStmtToIRBB( bb, IRStmt_Put( offB_LR, IRExpr_Tmp(old_LR)) );
736
 
   /* Branch to LR */
737
 
   /* re boring, we arrived here precisely because a wrapped fn did a
738
 
      blr (hence Ijk_Ret); so we should just mark this jump as Boring,
739
 
      else one _Call will have resulted in to _Rets. */
740
 
   bb->jumpkind = Ijk_Boring;
741
 
   bb->next = IRExpr_Binop(Iop_And64, IRExpr_Tmp(old_LR), mkU64(~(3ULL)));
 
935
#  if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
 
936
   Int    offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
 
937
   Int    offB_LR   = offsetof(VexGuestPPC64State,guest_LR);
 
938
   IRTemp old_R2    = newIRTemp( bb->tyenv, Ity_I64 );
 
939
   IRTemp old_LR    = newIRTemp( bb->tyenv, Ity_I64 );
 
940
   /* Restore R2 */
 
941
   old_R2 = gen_POP( bb );
 
942
   addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
 
943
   /* Restore LR */
 
944
   old_LR = gen_POP( bb );
 
945
   addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
 
946
   /* Branch to LR */
 
947
   /* re boring, we arrived here precisely because a wrapped fn did a
 
948
      blr (hence Ijk_Ret); so we should just mark this jump as Boring,
 
949
      else one _Call will have resulted in two _Rets. */
 
950
   bb->jumpkind = Ijk_Boring;
 
951
   bb->next = IRExpr_Binop(Iop_And64, IRExpr_RdTmp(old_LR), mkU64(~(3ULL)));
 
952
 
 
953
#  elif defined(VGP_ppc32_aix5)
 
954
   Int    offB_GPR2 = offsetof(VexGuestPPC32State,guest_GPR2);
 
955
   Int    offB_LR   = offsetof(VexGuestPPC32State,guest_LR);
 
956
   IRTemp old_R2    = newIRTemp( bb->tyenv, Ity_I32 );
 
957
   IRTemp old_LR    = newIRTemp( bb->tyenv, Ity_I32 );
 
958
   /* Restore R2 */
 
959
   old_R2 = gen_POP( bb );
 
960
   addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
 
961
   /* Restore LR */
 
962
   old_LR = gen_POP( bb );
 
963
   addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
 
964
 
 
965
   /* Branch to LR */
 
966
   /* re boring, we arrived here precisely because a wrapped fn did a
 
967
      blr (hence Ijk_Ret); so we should just mark this jump as Boring,
 
968
      else one _Call will have resulted in two _Rets. */
 
969
   bb->jumpkind = Ijk_Boring;
 
970
   bb->next = IRExpr_Binop(Iop_And32, IRExpr_RdTmp(old_LR), mkU32(~3));
 
971
 
 
972
#  else
 
973
#    error Platform is not TOC-afflicted, fortunately
 
974
#  endif
742
975
}
743
976
 
744
977
static
745
 
Bool mk_preamble__ppc64_magic_return_stub ( void* closureV, IRBB* bb )
 
978
Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb )
746
979
{
747
980
   VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
748
 
   /* Since we're creating the entire IRBB right here, give it a
 
981
   /* Since we're creating the entire IRSB right here, give it a
749
982
      proper IMark, as it won't get one any other way, and cachegrind
750
983
      will barf if it doesn't have one (fair enough really). */
751
 
   addStmtToIRBB( bb, IRStmt_IMark( closure->readdr, 4 ) );
 
984
   addStmtToIRSB( bb, IRStmt_IMark( closure->readdr, 4 ) );
752
985
   /* Generate the magic sequence:
753
986
         pop R2 from hidden stack
754
987
         pop LR from hidden stack
761
994
}
762
995
#endif
763
996
 
764
 
/* --------------- END ppc64-linux specific helpers --------------- */
765
 
 
766
 
/* This is an the IR preamble generators used for replacement
 
997
/* --------------- END helpers for with-TOC platforms --------------- */
 
998
 
 
999
 
 
1000
/* This is the IR preamble generator used for replacement
767
1001
   functions.  It adds code to set the guest_NRADDR{_GPR2} to zero
768
1002
   (technically not necessary, but facilitates detecting mixups in
769
1003
   which a replacement function has been erroneously declared using
770
1004
   VG_REPLACE_FUNCTION_Z{U,Z} when instead it should have been written
771
1005
   using VG_WRAP_FUNCTION_Z{U,Z}).
772
1006
 
773
 
   On ppc64-linux the follow hacks are also done: LR and R2 are pushed
774
 
   onto a hidden stack, sets R2 to the correct value for the
775
 
   replacement function, and sets LR to point at the magic return-stub
776
 
   address.  Setting LR causes the return of the wrapped/redirected
777
 
   function to lead to our magic return stub, which restores LR and R2
778
 
   from said stack and returns for real.
 
1007
   On with-TOC platforms the follow hacks are also done: LR and R2 are
 
1008
   pushed onto a hidden stack, R2 is set to the correct value for the
 
1009
   replacement function, and LR is set to point at the magic
 
1010
   return-stub address.  Setting LR causes the return of the
 
1011
   wrapped/redirected function to lead to our magic return stub, which
 
1012
   restores LR and R2 from said stack and returns for real.
779
1013
 
780
1014
   VG_(get_StackTrace2) understands that the LR value may point to the
781
1015
   return stub address, and that in that case it can get the real LR
782
1016
   value from the hidden stack instead. */
783
1017
static 
784
 
Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRBB* bb )
 
1018
Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
785
1019
{
786
1020
   Int nraddr_szB
787
1021
      = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
788
1022
   vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
789
 
   addStmtToIRBB( 
 
1023
   vg_assert(nraddr_szB == VG_WORDSIZE);
 
1024
   addStmtToIRSB( 
790
1025
      bb,
791
1026
      IRStmt_Put( 
792
1027
         offsetof(VexGuestArchState,guest_NRADDR),
793
1028
         nraddr_szB == 8 ? mkU64(0) : mkU32(0)
794
1029
      )
795
1030
   );
796
 
#  if defined(VGP_ppc64_linux)
 
1031
#  if defined(VG_PLAT_USES_PPCTOC)
797
1032
   { VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
798
 
     addStmtToIRBB(
 
1033
     addStmtToIRSB(
799
1034
        bb,
800
1035
        IRStmt_Put(
801
1036
           offsetof(VexGuestArchState,guest_NRADDR_GPR2),
802
 
           mkU64(0)
 
1037
           VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
803
1038
        )
804
1039
     );
805
1040
     gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
811
1046
/* Ditto, except set guest_NRADDR to nraddr (the un-redirected guest
812
1047
   address).  This is needed for function wrapping - so the wrapper
813
1048
   can read _NRADDR and find the address of the function being
814
 
   wrapped. */
 
1049
   wrapped.  On toc-afflicted platforms we must also snarf r2. */
815
1050
static 
816
 
Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRBB* bb )
 
1051
Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb )
817
1052
{
818
1053
   VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
819
1054
   Int nraddr_szB
820
1055
      = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
821
1056
   vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
822
 
   addStmtToIRBB( 
 
1057
   vg_assert(nraddr_szB == VG_WORDSIZE);
 
1058
   addStmtToIRSB( 
823
1059
      bb,
824
1060
      IRStmt_Put( 
825
1061
         offsetof(VexGuestArchState,guest_NRADDR),
828
1064
            : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
829
1065
      )
830
1066
   );
831
 
#  if defined(VGP_ppc64_linux)
832
 
   addStmtToIRBB( 
 
1067
#  if defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
 
1068
                               || defined(VGP_ppc64_aix5)
 
1069
   addStmtToIRSB( 
833
1070
      bb,
834
1071
      IRStmt_Put( 
835
1072
         offsetof(VexGuestArchState,guest_NRADDR_GPR2),
836
1073
         IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2), 
837
 
                    Ity_I64)
 
1074
                    VG_WORDSIZE==8 ? Ity_I64 : Ity_I32)
838
1075
      )
839
1076
   );
840
1077
   gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
842
1079
   return False;
843
1080
}
844
1081
 
 
1082
/* --- Helpers to do with PPC related stack redzones. --- */
 
1083
 
 
1084
__attribute__((unused))
 
1085
static Bool const_True ( Addr64 guest_addr )
 
1086
{
 
1087
   return True;
 
1088
}
 
1089
 
 
1090
__attribute__((unused))
 
1091
static Bool bl_RZ_zap_ok_for_AIX ( Addr64 bl_target )
 
1092
{
 
1093
   /* paranoia */
 
1094
   if (sizeof(void*) == 4)
 
1095
      bl_target &= 0xFFFFFFFFULL;
 
1096
 
 
1097
   /* don't zap the redzone for calls to millicode. */
 
1098
   if (bl_target < 0x10000ULL)
 
1099
      return False;
 
1100
 
 
1101
   /* don't zap the redzone for calls to .$SAVEF14 .. .$SAVEF31.
 
1102
      First we need to be reasonably sure we won't segfault by looking
 
1103
      at the branch target. */
 
1104
   { NSegment const*const seg = VG_(am_find_nsegment)( (Addr)bl_target );
 
1105
     if (seg && seg->hasR) {
 
1106
        switch ( *(UInt*)(Addr)bl_target ) {
 
1107
           case 0xd9c1ff70: /* stfd f14,-144(r1) */
 
1108
           case 0xd9e1ff78: /* stfd f15,-136(r1) */
 
1109
           case 0xda01ff80: /* stfd f16,-128(r1) */
 
1110
           case 0xda21ff88: /* stfd f17,-120(r1) */
 
1111
           case 0xda41ff90: /* stfd f18,-112(r1) */
 
1112
           case 0xda61ff98: /* stfd f19,-104(r1) */
 
1113
           case 0xda81ffa0: /* stfd f20,-96(r1) */
 
1114
           case 0xdaa1ffa8: /* stfd f21,-88(r1) */
 
1115
           case 0xdac1ffb0: /* stfd f22,-80(r1) */
 
1116
           case 0xdae1ffb8: /* stfd f23,-72(r1) */
 
1117
           case 0xdb01ffc0: /* stfd f24,-64(r1) */
 
1118
           case 0xdb21ffc8: /* stfd f25,-56(r1) */
 
1119
           case 0xdb41ffd0: /* stfd f26,-48(r1) */
 
1120
           case 0xdb61ffd8: /* stfd f27,-40(r1) */
 
1121
           case 0xdb81ffe0: /* stfd f28,-32(r1) */
 
1122
           case 0xdba1ffe8: /* stfd f29,-24(r1) */
 
1123
           case 0xdbc1fff0: /* stfd f30,-16(r1) */
 
1124
           case 0xdbe1fff8: /* stfd f31,-8(r1) */
 
1125
              return False;
 
1126
        }
 
1127
     }
 
1128
   }
 
1129
   return True;
 
1130
}
845
1131
 
846
1132
/* --------------- main translation function --------------- */
847
1133
 
885
1171
   Int                tmpbuf_used, verbosity, i;
886
1172
   Bool               notrace_until_done, do_self_check;
887
1173
   UInt               notrace_until_limit = 0;
888
 
   NSegment*          seg;
889
 
   Bool (*preamble_fn)(void*,IRBB*);
 
1174
   Bool (*preamble_fn)(void*,IRSB*);
890
1175
   VexArch            vex_arch;
891
1176
   VexArchInfo        vex_archinfo;
 
1177
   VexAbiInfo         vex_abiinfo;
892
1178
   VexGuestExtents    vge;
893
1179
   VexTranslateArgs   vta;
894
1180
   VexTranslateResult tres;
970
1256
 
971
1257
   /* Are we allowed to translate here? */
972
1258
 
973
 
   seg = VG_(am_find_nsegment)(addr);
 
1259
   { /* BEGIN new scope specially for 'seg' */
 
1260
   NSegment const* seg = VG_(am_find_nsegment)(addr);
974
1261
 
975
 
   if (!translations_allowable_from_seg(seg)) {
 
1262
   if ( (!translations_allowable_from_seg(seg))
 
1263
        || addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
 
1264
      if (VG_(clo_trace_signals))
 
1265
         VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%llx)"
 
1266
                                   " - throwing SEGV", addr);
976
1267
      /* U R busted, sonny.  Place your hands on your head and step
977
1268
         away from the orig_addr. */
978
1269
      /* Code address is bad - deliver a signal instead */
1009
1300
   else 
1010
1301
   if (kind == T_Redir_Wrap)
1011
1302
      preamble_fn = mk_preamble__set_NRADDR_to_nraddr;
1012
 
#  if defined(VGP_ppc64_linux)
1013
 
   if (nraddr == (Addr64)&VG_(ppc64_linux_magic_redirect_return_stub)) {
 
1303
 
 
1304
#  if defined(VG_PLAT_USES_PPCTOC)
 
1305
   if (ULong_to_Ptr(nraddr)
 
1306
       == (void*)&VG_(ppctoc_magic_redirect_return_stub)) {
1014
1307
      /* If entering the special return stub, this means a wrapped or
1015
1308
         redirected function is returning.  Make this translation one
1016
1309
         which restores R2 and LR from the thread's hidden redir
1018
1311
         really causing the function to return. */
1019
1312
      vg_assert(kind == T_Normal);
1020
1313
      vg_assert(nraddr == addr);
1021
 
      preamble_fn = mk_preamble__ppc64_magic_return_stub;
1022
 
    }
 
1314
      preamble_fn = mk_preamble__ppctoc_magic_return_stub;
 
1315
   }
1023
1316
#  endif
1024
1317
 
1025
1318
   /* ------ Actually do the translation. ------ */
1029
1322
   /* Get the CPU info established at startup. */
1030
1323
   VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1031
1324
 
 
1325
   /* Set up 'abiinfo' structure with stuff Vex needs to know about
 
1326
      the guest and host ABIs. */
 
1327
 
 
1328
   LibVEX_default_VexAbiInfo( &vex_abiinfo );
 
1329
   vex_abiinfo.guest_stack_redzone_size = VG_STACK_REDZONE_SZB;
 
1330
 
 
1331
#  if defined(VGP_ppc32_linux)
 
1332
   vex_abiinfo.guest_ppc_zap_RZ_at_blr        = False;
 
1333
   vex_abiinfo.guest_ppc_zap_RZ_at_bl         = NULL;
 
1334
   vex_abiinfo.host_ppc32_regalign_int64_args = True;
 
1335
#  endif
 
1336
#  if defined(VGP_ppc64_linux)
 
1337
   vex_abiinfo.guest_ppc_zap_RZ_at_blr        = True;
 
1338
   vex_abiinfo.guest_ppc_zap_RZ_at_bl         = const_True;
 
1339
   vex_abiinfo.host_ppc_calls_use_fndescrs    = True;
 
1340
#  endif
 
1341
#  if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
 
1342
   vex_abiinfo.guest_ppc_zap_RZ_at_blr        = False;
 
1343
   vex_abiinfo.guest_ppc_zap_RZ_at_bl         = bl_RZ_zap_ok_for_AIX;
 
1344
   vex_abiinfo.guest_ppc_sc_continues_at_LR   = True;
 
1345
   vex_abiinfo.host_ppc_calls_use_fndescrs    = True;
 
1346
#  endif
 
1347
 
1032
1348
   /* Set up closure args. */
1033
1349
   closure.tid    = tid;
1034
1350
   closure.nraddr = nraddr;
1039
1355
   vta.archinfo_guest   = vex_archinfo;
1040
1356
   vta.arch_host        = vex_arch;
1041
1357
   vta.archinfo_host    = vex_archinfo;
 
1358
   vta.abiinfo_both     = vex_abiinfo;
1042
1359
   vta.guest_bytes      = (UChar*)ULong_to_Ptr(addr);
1043
1360
   vta.guest_bytes_addr = (Addr64)addr;
1044
1361
   vta.callback_opaque  = (void*)&closure;
1054
1371
        VgCallbackClosure*.  Hence the following longwinded casts.
1055
1372
        They are entirely legal but longwinded so as to maximise the
1056
1373
        chance of the C typechecker picking up any type snafus. */
1057
 
     IRBB*(*f)(VgCallbackClosure*,
1058
 
               IRBB*,VexGuestLayout*,VexGuestExtents*,
 
1374
     IRSB*(*f)(VgCallbackClosure*,
 
1375
               IRSB*,VexGuestLayout*,VexGuestExtents*,
1059
1376
               IRType,IRType)
1060
1377
       = VG_(tdict).tool_instrument;
1061
 
     IRBB*(*g)(void*,
1062
 
               IRBB*,VexGuestLayout*,VexGuestExtents*,
 
1378
     IRSB*(*g)(void*,
 
1379
               IRSB*,VexGuestLayout*,VexGuestExtents*,
1063
1380
               IRType,IRType)
1064
 
       = (IRBB*(*)(void*,IRBB*,VexGuestLayout*,VexGuestExtents*,IRType,IRType))f;
 
1381
       = (IRSB*(*)(void*,IRSB*,VexGuestLayout*,VexGuestExtents*,IRType,IRType))f;
1065
1382
     vta.instrument1    = g;
1066
1383
   }
1067
1384
   /* No need for type kludgery here. */
1068
1385
   vta.instrument2      = need_to_handle_SP_assignment()
1069
1386
                             ? vg_SP_update_pass
1070
1387
                             : NULL;
 
1388
   vta.finaltidy        = VG_(needs).final_IR_tidy_pass
 
1389
                             ? VG_(tdict).tool_final_IR_tidy_pass
 
1390
                             : NULL;
1071
1391
   vta.do_self_check    = do_self_check;
1072
1392
   vta.traceflags       = verbosity;
1073
1393
 
1105
1425
      should already point to it. */
1106
1426
 
1107
1427
   vg_assert( vge.base[0] == (Addr64)addr );
1108
 
   if (seg->kind == SkFileC || seg->kind == SkAnonC)
1109
 
      seg->hasT = True; /* has cached code */
 
1428
   /* set 'translations taken from this segment' flag */
 
1429
   VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
 
1430
   } /* END new scope specially for 'seg' */
1110
1431
 
1111
1432
   for (i = 1; i < vge.n_used; i++) {
1112
 
      seg = VG_(am_find_nsegment)( vge.base[i] );
1113
 
      if (seg->kind == SkFileC || seg->kind == SkAnonC)
1114
 
         seg->hasT = True; /* has cached code */
 
1433
      NSegment const* seg 
 
1434
         = VG_(am_find_nsegment)( vge.base[i] );
 
1435
      /* set 'translations taken from this segment' flag */
 
1436
      VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
1115
1437
   }
1116
1438
 
1117
1439
   /* Copy data at trans_addr into the translation cache. */