From 803a8f2100bd19d6239f3e5d85c50d70c33fc531 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Fri, 23 Dec 2005 02:29:58 +0000 Subject: [PATCH] Deal with function pointer vs function entry crazyness on ppc64-linux. Memcheck is done, but any tool which generates IR helper calls will need to be similarly adulterated. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5418 --- coregrind/m_machine.c | 23 ++++++++++ coregrind/m_translate.c | 6 ++- include/pub_tool_machine.h | 6 +++ memcheck/mc_translate.c | 89 ++++++++++++++++++++++---------------- 4 files changed, 84 insertions(+), 40 deletions(-) diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 482a1f3354..80b58ecf12 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -499,6 +499,29 @@ void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa, } +// Given a pointer to a function as obtained by "& functionname" in C, +// produce a pointer to the actual entry point for the function. For +// most platforms it's the identity function. Unfortunately, on +// ppc64-linux it isn't (sigh). +void* VG_(fnptr_to_fnentry)( void* f ) +{ +#if defined(VGP_x86_linux) + return f; +#elif defined(VGP_amd64_linux) + return f; +#elif defined(VGP_ppc32_linux) + return f; +#elif defined(VGP_ppc64_linux) + /* f is a pointer to a 3-word function descriptor, of which + the first word is the entry address. */ + /* Don't ask me. Really. I have no idea why. */ + ULong* descr = (ULong*)f; + return (void*)(descr[0]); +#else +# error "Unknown platform" +#endif +} + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c index 09ce93dc41..5e0548ee65 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -241,7 +241,8 @@ IRBB* vg_SP_update_pass ( IRBB* bb_in, dcall = unsafeIRDirty_0_N( \ 1/*regparms*/, \ "track_" #kind "_mem_stack_" #syze, \ - VG_(tdict).track_##kind##_mem_stack_##syze, \ + VG_(fnptr_to_fnentry)( \ + VG_(tdict).track_##kind##_mem_stack_##syze ), \ mkIRExprVec_1(IRExpr_Tmp(tmpp)) \ ); \ dcall->nFxState = 1; \ @@ -341,7 +342,8 @@ IRBB* vg_SP_update_pass ( IRBB* bb_in, dcall = unsafeIRDirty_0_N( 2/*regparms*/, - "VG_(unknown_SP_update)", &VG_(unknown_SP_update), + "VG_(unknown_SP_update)", + VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ), mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data ) ); addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h index fe4d847343..948df5ac6c 100644 --- a/include/pub_tool_machine.h +++ b/include/pub_tool_machine.h @@ -84,6 +84,12 @@ extern void VG_(thread_stack_reset_iter) ( void ); extern Bool VG_(thread_stack_next) ( ThreadId* tid, Addr* stack_min, Addr* stack_max ); +// Given a pointer to a function as obtained by "& functionname" in C, +// produce a pointer to the actual entry point for the function. For +// most platforms it's the identity function. Unfortunately, on +// ppc64-linux it isn't (sigh). +extern void* VG_(fnptr_to_fnentry)( void* ); + #endif // __PUB_TOOL_MACHINE_H /*--------------------------------------------------------------------*/ diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c index c5e991a45a..46f8706724 100644 --- a/memcheck/mc_translate.c +++ b/memcheck/mc_translate.c @@ -30,10 +30,11 @@ */ #include "pub_tool_basics.h" -#include "pub_tool_hashtable.h" // For mac_shared.h +#include "pub_tool_hashtable.h" // For mac_shared.h #include "pub_tool_libcassert.h" #include "pub_tool_libcprint.h" #include "pub_tool_tooliface.h" +#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry) #include "mc_include.h" @@ -845,39 +846,44 @@ static void complainIfUndefined ( MCEnv* mce, IRAtom* atom ) switch (sz) { case 0: - di = unsafeIRDirty_0_N( 0/*regparms*/, - "MC_(helperc_value_check0_fail)", - &MC_(helperc_value_check0_fail), - mkIRExprVec_0() - ); + di = unsafeIRDirty_0_N( + 0/*regparms*/, + "MC_(helperc_value_check0_fail)", + VG_(fnptr_to_fnentry)( &MC_(helperc_value_check0_fail) ), + mkIRExprVec_0() + ); break; case 1: - di = unsafeIRDirty_0_N( 0/*regparms*/, - "MC_(helperc_value_check1_fail)", - &MC_(helperc_value_check1_fail), - mkIRExprVec_0() - ); + di = unsafeIRDirty_0_N( + 0/*regparms*/, + "MC_(helperc_value_check1_fail)", + VG_(fnptr_to_fnentry)( &MC_(helperc_value_check1_fail) ), + mkIRExprVec_0() + ); break; case 4: - di = unsafeIRDirty_0_N( 0/*regparms*/, - "MC_(helperc_value_check4_fail)", - &MC_(helperc_value_check4_fail), - mkIRExprVec_0() - ); + di = unsafeIRDirty_0_N( + 0/*regparms*/, + "MC_(helperc_value_check4_fail)", + VG_(fnptr_to_fnentry)( &MC_(helperc_value_check4_fail) ), + mkIRExprVec_0() + ); break; case 8: - di = unsafeIRDirty_0_N( 0/*regparms*/, - "MC_(helperc_value_check8_fail)", - &MC_(helperc_value_check8_fail), - mkIRExprVec_0() - ); + di = unsafeIRDirty_0_N( + 0/*regparms*/, + "MC_(helperc_value_check8_fail)", + VG_(fnptr_to_fnentry)( &MC_(helperc_value_check8_fail) ), + mkIRExprVec_0() + ); break; default: - di = unsafeIRDirty_0_N( 1/*regparms*/, - "MC_(helperc_complain_undef)", - &MC_(helperc_complain_undef), - mkIRExprVec_1( mkIRExpr_HWord( sz )) - ); + di = unsafeIRDirty_0_N( + 1/*regparms*/, + "MC_(helperc_complain_undef)", + VG_(fnptr_to_fnentry)( &MC_(helperc_complain_undef) ), + mkIRExprVec_1( mkIRExpr_HWord( sz )) + ); break; } di->guard = cond; @@ -2331,7 +2337,8 @@ IRAtom* expr2vbits_Load_WRK ( MCEnv* mce, read. */ datavbits = newIRTemp(mce->bb->tyenv, ty); di = unsafeIRDirty_1_N( datavbits, - 1/*regparms*/, hname, helper, + 1/*regparms*/, + hname, VG_(fnptr_to_fnentry)( helper ), mkIRExprVec_1( addrAct )); setHelperAnns( mce, di ); stmt( mce->bb, IRStmt_Dirty(di) ); @@ -2594,16 +2601,18 @@ void do_shadow_Store ( MCEnv* mce, addrLo64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasLo64) ); vdataLo64 = assignNew(mce, Ity_I64, unop(Iop_V128to64, vdata)); diLo64 = unsafeIRDirty_0_N( - 1/*regparms*/, hname, helper, - mkIRExprVec_2( addrLo64, vdataLo64 )); - + 1/*regparms*/, + hname, VG_(fnptr_to_fnentry)( helper ), + mkIRExprVec_2( addrLo64, vdataLo64 ) + ); eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64); addrHi64 = assignNew(mce, tyAddr, binop(mkAdd, addr, eBiasHi64) ); vdataHi64 = assignNew(mce, Ity_I64, unop(Iop_V128HIto64, vdata)); diHi64 = unsafeIRDirty_0_N( - 1/*regparms*/, hname, helper, - mkIRExprVec_2( addrHi64, vdataHi64 )); - + 1/*regparms*/, + hname, VG_(fnptr_to_fnentry)( helper ), + mkIRExprVec_2( addrHi64, vdataHi64 ) + ); setHelperAnns( mce, diLo64 ); setHelperAnns( mce, diHi64 ); stmt( mce->bb, IRStmt_Dirty(diLo64) ); @@ -2625,13 +2634,17 @@ void do_shadow_Store ( MCEnv* mce, the back ends aren't clever enough to handle 64-bit regparm args. Therefore be different. */ di = unsafeIRDirty_0_N( - 1/*regparms*/, hname, helper, - mkIRExprVec_2( addrAct, vdata )); + 1/*regparms*/, + hname, VG_(fnptr_to_fnentry)( helper ), + mkIRExprVec_2( addrAct, vdata ) + ); } else { di = unsafeIRDirty_0_N( - 2/*regparms*/, hname, helper, + 2/*regparms*/, + hname, VG_(fnptr_to_fnentry)( helper ), mkIRExprVec_2( addrAct, - zwidenToHostWord( mce, vdata ))); + zwidenToHostWord( mce, vdata )) + ); } setHelperAnns( mce, di ); stmt( mce->bb, IRStmt_Dirty(di) ); @@ -2849,7 +2862,7 @@ void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len ) di = unsafeIRDirty_0_N( 0/*regparms*/, "MC_(helperc_MAKE_STACK_UNINIT)", - &MC_(helperc_MAKE_STACK_UNINIT), + VG_(fnptr_to_fnentry)( &MC_(helperc_MAKE_STACK_UNINIT) ), mkIRExprVec_2( base, mkIRExpr_HWord( (UInt)len) ) ); stmt( mce->bb, IRStmt_Dirty(di) ); -- 2.47.3