275
280
clear_SP_aliases();
277
for (i = 0; i < bb_in->stmts_used; i++) {
282
for (i = 0; i < sb_in->stmts_used; i++) {
279
st = bb_in->stmts[i];
284
st = sb_in->stmts[i];
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 );
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);
304
add_SP_alias(st->Ist.Tmp.tmp, delta - con);
311
add_SP_alias(st->Ist.WrTmp.tmp, delta - con);
306
addStmtToIRBB( bb, st );
313
addStmtToIRSB( bb, st );
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 );
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
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;
337
+ sizeofIRType( typeOfIRExpr( bb->tyenv, st->Ist.Put.data ))
339
vg_assert(first_SP <= last_SP);
340
vg_assert(first_Put <= last_Put);
342
if (last_Put < first_SP || last_SP < first_Put)
343
goto case5; /* no overlap */
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
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);
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;
347
381
/* common values for ppc64: 144 128 160 112 176 */
348
382
n_SP_updates_generic_known++;
386
/* Deal with an unknown update to SP. We're here because
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
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
353
399
n_SP_updates_generic_unknown++;
359
405
/* Pass both the old and new SP values to this helper. */
360
406
old_SP = newIRTemp(bb->tyenv, typeof_SP);
363
IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
409
IRStmt_WrTmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
366
dcall = unsafeIRDirty_0_N(
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 )
372
addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
374
addStmtToIRBB( bb, st );
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(
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 )
423
addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
424
/* don't forget the original assignment */
425
addStmtToIRSB( bb, st );
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
440
addStmtToIRSB( bb, st );
442
new_SP = newIRTemp(bb->tyenv, typeof_SP);
445
IRStmt_WrTmp( new_SP, IRExpr_Get(offset_SP, typeof_SP) )
448
addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(old_SP) ));
450
dcall = unsafeIRDirty_0_N(
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))
457
addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
459
addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(new_SP) ));
462
/* Forget what we already know. */
376
463
clear_SP_aliases();
377
add_SP_alias(st->Ist.Put.data->Iex.Tmp.tmp, 0);
465
/* If this is a Put of a tmp that exactly updates SP,
466
start tracking aliases against this tmp. */
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)
472
add_SP_alias(st->Ist.Put.data->Iex.RdTmp.tmp, 0);
591
703
static IRExpr* mkU32 ( UInt n ) {
592
704
return IRExpr_Const(IRConst_U32(n));
594
#if defined(VGP_ppc64_linux)
707
#if defined(VG_PLAT_USES_PPCTOC)
595
708
static IRExpr* mkU8 ( UChar n ) {
596
709
return IRExpr_Const(IRConst_U8(n));
599
static void gen_PUSH ( IRBB* bb, IRExpr* e )
711
static IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) {
712
if (typeOfIRExpr(tyenv, e) == Ity_I32) {
715
vg_assert(typeOfIRExpr(tyenv, e) == Ity_I64);
716
return IRExpr_Unop(Iop_64to32, e);
720
/* Generate code to push word-typed expression 'e' onto this thread's
721
redir stack, checking for stack overflow and generating code to
724
static void gen_PUSH ( IRSB* bb, IRExpr* e )
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);
606
IRArray* descr = mkIRArray( offB_REDIR_STACK, Ity_I64, stack_size );
607
IRTemp t1 = newIRTemp( bb->tyenv, Ity_I64 );
608
IRExpr* one = mkU64(1);
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);
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);
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);
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);
758
vg_assert(sizeof(void*) == VG_WORDSIZE);
759
vg_assert(sizeof(Word) == VG_WORDSIZE);
760
vg_assert(sizeof(Addr) == VG_WORDSIZE);
762
descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
763
t1 = newIRTemp( bb->tyenv, ty_Word );
766
vg_assert(typeOfIRExpr(bb->tyenv, e) == ty_Word);
610
768
/* t1 = guest_REDIR_SP + 1 */
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)
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. */
626
784
IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_overflow))
635
IRExpr_Binop(Iop_Sub64,mkU64(stack_size-1),IRExpr_Tmp(t1)),
793
IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_RdTmp(t1)),
794
mkU8(8 * VG_WORDSIZE - 1)
799
is64 ? IRConst_U64(0) : IRConst_U32(0)
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)));
648
806
/* guest_REDIR_STACK[t1+0] = e */
807
/* PutI/GetI have I32-typed indexes regardless of guest word size */
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)
655
static IRTemp gen_POP ( IRBB* bb )
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. */
819
static IRTemp gen_POP ( IRSB* bb )
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);
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);
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;
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);
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;
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);
850
vg_assert(sizeof(void*) == VG_WORDSIZE);
851
vg_assert(sizeof(Word) == VG_WORDSIZE);
852
vg_assert(sizeof(Addr) == VG_WORDSIZE);
667
854
/* t1 = guest_REDIR_SP */
670
IRStmt_Tmp( t1, IRExpr_Get( offB_REDIR_SP, Ity_I64 ) )
857
IRStmt_WrTmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) )
673
860
/* Bomb out if t1 < 0. Same comments as gen_PUSH apply. */
676
863
IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_underflow))
873
mkU8(8 * VG_WORDSIZE - 1)
878
is64 ? IRConst_U64(0) : IRConst_U32(0)
695
882
/* res = guest_REDIR_STACK[t1+0] */
883
/* PutI/GetI have I32-typed indexes regardless of guest word size */
700
IRExpr_GetI(descr, IRExpr_Unop(Iop_64to32,IRExpr_Tmp(t1)), 0)
888
IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0)
704
892
/* guest_REDIR_SP = t1-1 */
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))
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
908
static void gen_push_and_set_LR_R2 ( IRSB* bb, Addr64 new_R2_value )
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 )) );
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 )) );
929
# error Platform is not TOC-afflicted, fortunately
724
static void gen_pop_R2_LR_then_bLR ( IRBB* bb )
933
static void gen_pop_R2_LR_then_bLR ( IRSB* bb )
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 );
731
old_R2 = gen_POP( bb );
732
addStmtToIRBB( bb, IRStmt_Put( offB_GPR2, IRExpr_Tmp(old_R2)) );
734
old_LR = gen_POP( bb );
735
addStmtToIRBB( bb, IRStmt_Put( offB_LR, IRExpr_Tmp(old_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 );
941
old_R2 = gen_POP( bb );
942
addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
944
old_LR = gen_POP( bb );
945
addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_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)));
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 );
959
old_R2 = gen_POP( bb );
960
addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
962
old_LR = gen_POP( bb );
963
addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_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));
973
# error Platform is not TOC-afflicted, fortunately
745
Bool mk_preamble__ppc64_magic_return_stub ( void* closureV, IRBB* bb )
978
Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb )
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
764
/* --------------- END ppc64-linux specific helpers --------------- */
766
/* This is an the IR preamble generators used for replacement
997
/* --------------- END helpers for with-TOC platforms --------------- */
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}).
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.
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. */
784
Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRBB* bb )
1018
Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
787
1021
= sizeof(((VexGuestArchState*)0)->guest_NRADDR);
788
1022
vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
1023
vg_assert(nraddr_szB == VG_WORDSIZE);
792
1027
offsetof(VexGuestArchState,guest_NRADDR),
793
1028
nraddr_szB == 8 ? mkU64(0) : mkU32(0)
796
# if defined(VGP_ppc64_linux)
1031
# if defined(VG_PLAT_USES_PPCTOC)
797
1032
{ VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
801
1036
offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1037
VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
805
1040
gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );