--- valgrind-3.3.0/memcheck/mc_main.c 2007-12-10 15:18:22.000000000 -0800 +++ valgrind-3.3.0.new/memcheck/mc_main-asap.c 2007-12-31 13:43:30.000000000 -0800 @@ -30,6 +30,11 @@ The GNU General Public License is contained in the file COPYING. */ +/* The changes for "--complain-asap=yes" and LoadUninit are + * Copyright 2007 BitWagon Software LLC. All rights reserved. + * Licensed under GNU General Public License, verion 2 (GNU GPLv2). + */ + #include "pub_tool_basics.h" #include "pub_tool_aspacemgr.h" #include "pub_tool_hashtable.h" // For mc_include.h @@ -1135,6 +1140,7 @@ /* --------------- Load/store slow cases. --------------- */ +Int MC_(clo_complain_asap) = False; // Forward declarations static void mc_record_address_error ( ThreadId tid, Addr a, Int size, Bool isWrite ); @@ -1143,6 +1149,7 @@ static void mc_record_memparam_error ( ThreadId tid, Addr a, Bool isAddrErr, Char* msg ); static void mc_record_jump_error ( ThreadId tid, Addr a ); +static void mc_record_loaduninit_error (Addr a, Int size); static #ifndef PERF_FAST_LOADV @@ -1155,12 +1162,13 @@ the bytes in the word, from the most significant down to the least. */ ULong vbits64 = V_BITS64_UNDEFINED; - SizeT szB = nBits / 8; + SizeT const szB = nBits / 8; SSizeT i = szB-1; // Must be signed SizeT n_addrs_bad = 0; Addr ai; Bool partial_load_exemption_applies; UChar vbits8; + UChar vbsum; Bool ok; PROF_EVENT(30, "mc_LOADVn_slow"); @@ -1180,8 +1188,11 @@ UWord vabits16 = ((UShort*)(sm->vabits8))[sm_off16]; if (EXPECTED_TAKEN(vabits16 == VA_BITS16_DEFINED)) return V_BITS64_DEFINED; - if (EXPECTED_TAKEN(vabits16 == VA_BITS16_UNDEFINED)) + if (EXPECTED_TAKEN(vabits16 == VA_BITS16_UNDEFINED)) { + if (MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, 8); return V_BITS64_UNDEFINED; + } /* else fall into the slow case */ } if (EXPECTED_TAKEN(sizeof(void*) == 8 @@ -1191,19 +1202,24 @@ UWord vabits8 = sm->vabits8[sm_off]; if (EXPECTED_TAKEN(vabits8 == VA_BITS8_DEFINED)) return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_DEFINED); - if (EXPECTED_TAKEN(vabits8 == VA_BITS8_UNDEFINED)) + if (EXPECTED_TAKEN(vabits8 == VA_BITS8_UNDEFINED)) { + if (MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, 4); return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_UNDEFINED); + } /* else fall into slow case */ } /* ------------ END semi-fast cases ------------ */ tl_assert(nBits == 64 || nBits == 32 || nBits == 16 || nBits == 8); + vbsum = 0; for (i = szB-1; i >= 0; i--) { PROF_EVENT(31, "mc_LOADVn_slow(loop)"); ai = a + byte_offset_w(szB, bigendian, i); ok = get_vbits8(ai, &vbits8); if (!ok) n_addrs_bad++; + vbsum |= vbits8; vbits64 <<= 8; vbits64 |= vbits8; } @@ -1229,6 +1245,8 @@ if (n_addrs_bad > 0 && !partial_load_exemption_applies) mc_record_address_error( VG_(get_running_tid)(), a, szB, False ); + if (vbsum && MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, szB); return vbits64; } @@ -2681,6 +2699,7 @@ Err_Overlap, Err_Leak, Err_IllegalMempool, + Err_LoadUninit, } MC_ErrorTag; @@ -2769,6 +2788,12 @@ AddrInfo ai; } IllegalMempool; + // Fetch of uninitialized bits. + struct { + AddrInfo ai; + Int szB; // Size in bytes + } LoadUninit; + } Err; }; @@ -2922,6 +2947,13 @@ &extra->Err.MemParam.ai, False); break; + case Err_LoadUninit: + mc_pp_msg("LoadUninit", err, "load of uninit bits in %d bytes", + extra->Err.LoadUninit.szB); + mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.LoadUninit.ai, + False); + break; + case Err_User: mc_pp_msg("ClientCheck", err, "%s byte(s) found during client check request", @@ -2954,6 +2986,8 @@ mc_pp_msg("InvalidRead", err, "Invalid read of size %d", extra->Err.Addr.szB); + mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Addr.ai, + extra->Err.Addr.maybe_gcc); } mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Addr.ai, extra->Err.Addr.maybe_gcc); @@ -3233,6 +3267,14 @@ VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra ); } +static void mc_record_loaduninit_error(Addr a, Int szB) +{ + MC_Error extra; + extra.Err.LoadUninit.ai.tag = Addr_Undescribed; + extra.Err.LoadUninit.szB = szB; + VG_(maybe_record_error)( VG_(get_running_tid)(), Err_LoadUninit, a, NULL, &extra ); +} + /*------------------------------------------------------------*/ /*--- Other error operations ---*/ /*------------------------------------------------------------*/ @@ -3281,6 +3323,7 @@ case Err_IllegalMempool: case Err_Overlap: case Err_Cond: + case Err_LoadUninit: return True; case Err_Addr: @@ -3413,6 +3456,10 @@ describe_addr ( VG_(get_error_address)(err), &extra->Err.IllegalMempool.ai ); return sizeof(MC_Error); + case Err_LoadUninit: + describe_addr ( VG_(get_error_address)(err), &extra->Err.LoadUninit.ai ); + return sizeof(MC_Error); + // Err_FreeMismatches have already had their address described; this is // possible because we have the MC_Chunk on hand when the error is @@ -3454,6 +3501,10 @@ OverlapSupp, // Overlapping blocks in memcpy(), strcpy(), etc LeakSupp, // Something to be suppressed in a leak check. MempoolSupp, // Memory pool suppression. + + // Load uninitilaized bits from given size + Load1Supp, Load2Supp, Load4Supp, Load8Supp, Load16Supp, + } MC_SuppKind; @@ -3481,6 +3532,11 @@ else if (VG_STREQ(name, "Value4")) skind = Value4Supp; else if (VG_STREQ(name, "Value8")) skind = Value8Supp; else if (VG_STREQ(name, "Value16")) skind = Value16Supp; + else if (VG_STREQ(name, "Load1")) skind = Load1Supp; + else if (VG_STREQ(name, "Load2")) skind = Load2Supp; + else if (VG_STREQ(name, "Load4")) skind = Load4Supp; + else if (VG_STREQ(name, "Load8")) skind = Load8Supp; + else if (VG_STREQ(name, "Load16")) skind = Load16Supp; else return False; @@ -3540,6 +3596,14 @@ addr_case: return (ekind == Err_Addr && extra->Err.Addr.szB == su_szB); + case Load1Supp: su_szB = 1; goto load_case; + case Load2Supp: su_szB = 2; goto load_case; + case Load4Supp: su_szB = 4; goto load_case; + case Load8Supp: su_szB = 8; goto load_case; + case Load16Supp:su_szB =16; goto load_case; + load_case: + return (ekind == Err_LoadUninit && extra->Err.LoadUninit.szB == su_szB); + case JumpSupp: return (ekind == Err_Jump); @@ -3662,7 +3726,10 @@ // Convert V bits from compact memory form to expanded register form. if (EXPECTED_TAKEN(vabits16 == VA_BITS16_DEFINED)) { return V_BITS64_DEFINED; - } else if (EXPECTED_TAKEN(vabits16 == VA_BITS16_UNDEFINED)) { + } + if (MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, 8); + if (EXPECTED_TAKEN(vabits16 == VA_BITS16_UNDEFINED)) { return V_BITS64_UNDEFINED; } else { /* Slow case: the 8 bytes are not all-defined or all-undefined. */ @@ -3768,7 +3835,10 @@ // Almost certainly not necessary, but be paranoid. if (EXPECTED_TAKEN(vabits8 == VA_BITS8_DEFINED)) { return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_DEFINED); - } else if (EXPECTED_TAKEN(vabits8 == VA_BITS8_UNDEFINED)) { + } + if (MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, 4); + if (EXPECTED_TAKEN(vabits8 == VA_BITS8_UNDEFINED)) { return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_UNDEFINED); } else { /* Slow case: the 4 bytes are not all-defined or all-undefined. */ @@ -3902,13 +3972,19 @@ // addressible. // Convert V bits from compact memory form to expanded register form if (vabits8 == VA_BITS8_DEFINED ) { return V_BITS16_DEFINED; } - else if (vabits8 == VA_BITS8_UNDEFINED) { return V_BITS16_UNDEFINED; } + else if (vabits8 == VA_BITS8_UNDEFINED) { + if (MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, 2); + return V_BITS16_UNDEFINED; + } else { // The 4 (yes, 4) bytes are not all-defined or all-undefined, check // the two sub-bytes. UChar vabits4 = extract_vabits4_from_vabits8(a, vabits8); if (vabits4 == VA_BITS4_DEFINED ) { return V_BITS16_DEFINED; } - else if (vabits4 == VA_BITS4_UNDEFINED) { return V_BITS16_UNDEFINED; } + if (MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, 2); + if (vabits4 == VA_BITS4_UNDEFINED) { return V_BITS16_UNDEFINED; } else { /* Slow case: the two bytes are not all-defined or all-undefined. */ PROF_EVENT(242, "mc_LOADV16-slow2"); @@ -4010,13 +4086,19 @@ // Handle common case quickly: a is mapped, and the entire // word32 it lives in is addressible. if (vabits8 == VA_BITS8_DEFINED ) { return V_BITS8_DEFINED; } - else if (vabits8 == VA_BITS8_UNDEFINED) { return V_BITS8_UNDEFINED; } + else if (vabits8 == VA_BITS8_UNDEFINED) { + if (MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, 1); + return V_BITS8_UNDEFINED; + } else { // The 4 (yes, 4) bytes are not all-defined or all-undefined, check // the single byte. UChar vabits2 = extract_vabits2_from_vabits8(a, vabits8); if (vabits2 == VA_BITS2_DEFINED ) { return V_BITS8_DEFINED; } - else if (vabits2 == VA_BITS2_UNDEFINED) { return V_BITS8_UNDEFINED; } + if (MC_(clo_complain_asap)) + mc_record_loaduninit_error(a, 1); + if (vabits2 == VA_BITS2_UNDEFINED) { return V_BITS8_UNDEFINED; } else { /* Slow case: the byte is not all-defined or all-undefined. */ PROF_EVENT(262, "mc_LOADV8-slow2"); @@ -4379,6 +4461,7 @@ static Bool mc_process_cmd_line_options(Char* arg) { VG_BOOL_CLO(arg, "--partial-loads-ok", MC_(clo_partial_loads_ok)) + else VG_BOOL_CLO(arg, "--complain-asap", MC_(clo_complain_asap)) else VG_BOOL_CLO(arg, "--show-reachable", MC_(clo_show_reachable)) else VG_BOOL_CLO(arg, "--workaround-gcc296-bugs",MC_(clo_workaround_gcc296_bugs))