summaryrefslogtreecommitdiff
path: root/memcheck/mc_main.c
diff options
context:
space:
mode:
authorsewardj <sewardj@a5019735-40e9-0310-863c-91ae7b9d1cf9>2008-05-02 10:33:15 +0000
committersewardj <sewardj@a5019735-40e9-0310-863c-91ae7b9d1cf9>2008-05-02 10:33:15 +0000
commit7ce7166aeae2d8401f2b3b1f9e6f60be9ae9dd72 (patch)
tree392a4760bfb603e6a9150cc45534bdcc14b5abfe /memcheck/mc_main.c
parentfb27ca7c4f793dea4e95e01c5e1a9b7b0a4288ba (diff)
Move the error management code for Memcheck into a new file,
mc_errors.c, as it is relatively self contained. This reduces the size of mc_main.c by about 1350 lines. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7986 a5019735-40e9-0310-863c-91ae7b9d1cf9
Diffstat (limited to 'memcheck/mc_main.c')
-rw-r--r--memcheck/mc_main.c1434
1 files changed, 64 insertions, 1370 deletions
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c
index e4b7e133..a89d3c49 100644
--- a/memcheck/mc_main.c
+++ b/memcheck/mc_main.c
@@ -1027,7 +1027,7 @@ typedef
static IgnoreRanges ignoreRanges;
-static INLINE Bool in_ignored_range ( Addr a )
+INLINE Bool MC_(in_ignored_range) ( Addr a )
{
Int i;
if (LIKELY(ignoreRanges.used == 0))
@@ -1137,15 +1137,6 @@ static Bool parse_ignore_ranges ( UChar* str0 )
/* --------------- Load/store slow cases. --------------- */
-// Forward declarations
-static void mc_record_address_error ( ThreadId tid, Addr a,
- Int size, Bool isWrite );
-static void mc_record_core_mem_error ( ThreadId tid, Bool isAddrErr, Char* s );
-static void mc_record_regparam_error ( ThreadId tid, Char* msg, UInt otag );
-static void mc_record_memparam_error ( ThreadId tid, Addr a,
- Bool isAddrErr, Char* msg, UInt otag );
-static void mc_record_jump_error ( ThreadId tid, Addr a );
-
static
#ifndef PERF_FAST_LOADV
INLINE
@@ -1229,7 +1220,7 @@ ULong mc_LOADVn_slow ( Addr a, SizeT nBits, Bool bigendian )
&& n_addrs_bad < VG_WORDSIZE;
if (n_addrs_bad > 0 && !partial_load_exemption_applies)
- mc_record_address_error( VG_(get_running_tid)(), a, szB, False );
+ MC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
return vbits64;
}
@@ -1318,7 +1309,7 @@ void mc_STOREVn_slow ( Addr a, SizeT nBits, ULong vbytes, Bool bigendian )
/* If an address error has happened, report it. */
if (n_addrs_bad > 0)
- mc_record_address_error( VG_(get_running_tid)(), a, szB, True );
+ MC_(record_address_error)( VG_(get_running_tid)(), a, szB, True );
}
@@ -3387,12 +3378,12 @@ void check_mem_is_addressable ( CorePart part, ThreadId tid, Char* s,
if (!ok) {
switch (part) {
case Vg_CoreSysCall:
- mc_record_memparam_error ( tid, bad_addr,
- /*isAddrErr*/True, s, 0/*otag*/ );
+ MC_(record_memparam_error) ( tid, bad_addr,
+ /*isAddrErr*/True, s, 0/*otag*/ );
break;
case Vg_CoreSignal:
- mc_record_core_mem_error( tid, /*isAddrErr*/True, s );
+ MC_(record_core_mem_error)( tid, /*isAddrErr*/True, s );
break;
default:
@@ -3414,14 +3405,14 @@ void check_mem_is_defined ( CorePart part, ThreadId tid, Char* s,
switch (part) {
case Vg_CoreSysCall:
- mc_record_memparam_error ( tid, bad_addr, isAddrErr, s,
- isAddrErr ? 0 : otag );
+ MC_(record_memparam_error) ( tid, bad_addr, isAddrErr, s,
+ isAddrErr ? 0 : otag );
break;
/* If we're being asked to jump to a silly address, record an error
message before potentially crashing the entire system. */
case Vg_CoreTranslate:
- mc_record_jump_error( tid, bad_addr );
+ MC_(record_jump_error)( tid, bad_addr );
break;
default:
@@ -3442,8 +3433,8 @@ void check_mem_is_defined_asciiz ( CorePart part, ThreadId tid,
res = mc_is_defined_asciiz ( (Addr)str, &bad_addr, &otag );
if (MC_Ok != res) {
Bool isAddrErr = ( MC_AddrErr == res ? True : False );
- mc_record_memparam_error ( tid, bad_addr, isAddrErr, s,
- isAddrErr ? 0 : otag );
+ MC_(record_memparam_error) ( tid, bad_addr, isAddrErr, s,
+ isAddrErr ? 0 : otag );
}
}
@@ -3561,1264 +3552,9 @@ static void mc_pre_reg_read ( CorePart part, ThreadId tid, Char* s,
/* We've found some undefinedness. See if we can also find an
origin for it. */
otag = mb_get_origin_for_guest_offset( tid, offset, size );
- mc_record_regparam_error ( tid, s, otag );
-}
-
-
-/*------------------------------------------------------------*/
-/*--- Error types ---*/
-/*------------------------------------------------------------*/
-
-/* Did we show to the user, any errors for which an uninitialised
- value origin could have been collected (but wasn't) ? If yes,
- then, at the end of the run, print a 1 line message advising that a
- rerun with --track-origins=yes might help. */
-static Bool any_value_errors = False;
-
-
-// Different kinds of blocks.
-typedef enum {
- Block_Mallocd = 111,
- Block_Freed,
- Block_Mempool,
- Block_MempoolChunk,
- Block_UserG
-} BlockKind;
-
-/* ------------------ Addresses -------------------- */
-
-/* The classification of a faulting address. */
-typedef
- enum {
- Addr_Undescribed, // as-yet unclassified
- Addr_Unknown, // classification yielded nothing useful
- Addr_Block, // in malloc'd/free'd block
- Addr_Stack, // on a thread's stack
- Addr_DataSym, // in a global data sym
- Addr_Variable, // variable described by the debug info
- Addr_SectKind // last-ditch classification attempt
- }
- AddrTag;
-
-typedef
- struct _AddrInfo
- AddrInfo;
-
-struct _AddrInfo {
- AddrTag tag;
- union {
- // As-yet unclassified.
- struct { } Undescribed;
-
- // On a stack.
- struct {
- ThreadId tid; // Which thread's stack?
- } Stack;
-
- // This covers heap blocks (normal and from mempools) and user-defined
- // blocks.
- struct {
- BlockKind block_kind;
- Char* block_desc; // "block", "mempool" or user-defined
- SizeT block_szB;
- OffT rwoffset;
- ExeContext* lastchange;
- } Block;
-
- // In a global .data symbol. This holds the first 63 chars of
- // the variable's (zero terminated), plus an offset.
- struct {
- Char name[128];
- OffT offset;
- } DataSym;
-
- // Is described by Dwarf debug info. Arbitrary strings. Must
- // be the same length.
- struct {
- Char descr1[96];
- Char descr2[96];
- } Variable;
-
- // Could only narrow it down to be the PLT/GOT/etc of a given
- // object. Better than nothing, perhaps.
- struct {
- Char objname[128];
- VgSectKind kind;
- } SectKind;
-
- // Classification yielded nothing useful.
- struct { } Unknown;
-
- } Addr;
-};
-
-/* ------------------ Errors ----------------------- */
-
-/* What kind of error it is. */
-typedef
- enum {
- Err_Value,
- Err_Cond,
- Err_CoreMem,
- Err_Addr,
- Err_Jump,
- Err_RegParam,
- Err_MemParam,
- Err_User,
- Err_Free,
- Err_FreeMismatch,
- Err_Overlap,
- Err_Leak,
- Err_IllegalMempool,
- }
- MC_ErrorTag;
-
-
-typedef struct _MC_Error MC_Error;
-
-struct _MC_Error {
- // Nb: we don't need the tag here, as it's stored in the Error type! Yuk.
- //MC_ErrorTag tag;
-
- union {
- // Use of an undefined value:
- // - as a pointer in a load or store
- // - as a jump target
- struct {
- SizeT szB; // size of value in bytes
- // Origin info
- UInt otag; // origin tag
- ExeContext* origin_ec; // filled in later
- } Value;
-
- // Use of an undefined value in a conditional branch or move.
- struct {
- // Origin info
- UInt otag; // origin tag
- ExeContext* origin_ec; // filled in later
- } Cond;
-
- // Addressability error in core (signal-handling) operation.
- // It would be good to get rid of this error kind, merge it with
- // another one somehow.
- struct {
- } CoreMem;
-
- // Use of an unaddressable memory location in a load or store.
- struct {
- Bool isWrite; // read or write?
- SizeT szB; // not used for exec (jump) errors
- Bool maybe_gcc; // True if just below %esp -- could be a gcc bug
- AddrInfo ai;
- } Addr;
-
- // Jump to an unaddressable memory location.
- struct {
- AddrInfo ai;
- } Jump;
-
- // System call register input contains undefined bytes.
- struct {
- // Origin info
- UInt otag; // origin tag
- ExeContext* origin_ec; // filled in later
- } RegParam;
-
- // System call memory input contains undefined/unaddressable bytes
- struct {
- Bool isAddrErr; // Addressability or definedness error?
- AddrInfo ai;
- // Origin info
- UInt otag; // origin tag
- ExeContext* origin_ec; // filled in later
- } MemParam;
-
- // Problem found from a client request like CHECK_MEM_IS_ADDRESSABLE.
- struct {
- Bool isAddrErr; // Addressability or definedness error?
- AddrInfo ai;
- // Origin info
- UInt otag; // origin tag
- ExeContext* origin_ec; // filled in later
- } User;
-
- // Program tried to free() something that's not a heap block (this
- // covers double-frees). */
- struct {
- AddrInfo ai;
- } Free;
-
- // Program allocates heap block with one function
- // (malloc/new/new[]/custom) and deallocates with not the matching one.
- struct {
- AddrInfo ai;
- } FreeMismatch;
-
- // Call to strcpy, memcpy, etc, with overlapping blocks.
- struct {
- Addr src; // Source block
- Addr dst; // Destination block
- Int szB; // Size in bytes; 0 if unused.
- } Overlap;
-
- // A memory leak.
- struct {
- UInt n_this_record;
- UInt n_total_records;
- LossRecord* lossRecord;
- } Leak;
-
- // A memory pool error.
- struct {
- AddrInfo ai;
- } IllegalMempool;
-
- } Err;
-};
-
-
-/*------------------------------------------------------------*/
-/*--- Printing errors ---*/
-/*------------------------------------------------------------*/
-
-static void mc_pp_AddrInfo ( Addr a, AddrInfo* ai, Bool maybe_gcc )
-{
- HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
- HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
-
- switch (ai->tag) {
- case Addr_Unknown:
- if (maybe_gcc) {
- VG_(message)(Vg_UserMsg,
- "%sAddress 0x%llx is just below the stack ptr. "
- "To suppress, use: --workaround-gcc296-bugs=yes%s",
- xpre, (ULong)a, xpost
- );
- } else {
- VG_(message)(Vg_UserMsg,
- "%sAddress 0x%llx "
- "is not stack'd, malloc'd or (recently) free'd%s",
- xpre, (ULong)a, xpost);
- }
- break;
-
- case Addr_Stack:
- VG_(message)(Vg_UserMsg,
- "%sAddress 0x%llx is on thread %d's stack%s",
- xpre, (ULong)a, ai->Addr.Stack.tid, xpost);
- break;
-
- case Addr_Block: {
- SizeT block_szB = ai->Addr.Block.block_szB;
- OffT rwoffset = ai->Addr.Block.rwoffset;
- SizeT delta;
- const Char* relative;
-
- if (rwoffset < 0) {
- delta = (SizeT)(-rwoffset);
- relative = "before";
- } else if (rwoffset >= block_szB) {
- delta = rwoffset - block_szB;
- relative = "after";
- } else {
- delta = rwoffset;
- relative = "inside";
- }
- VG_(message)(Vg_UserMsg,
- "%sAddress 0x%lx is %,lu bytes %s a %s of size %,lu %s%s",
- xpre,
- a, delta, relative, ai->Addr.Block.block_desc,
- block_szB,
- ai->Addr.Block.block_kind==Block_Mallocd ? "alloc'd"
- : ai->Addr.Block.block_kind==Block_Freed ? "free'd"
- : "client-defined",
- xpost);
- VG_(pp_ExeContext)(ai->Addr.Block.lastchange);
- break;
- }
-
- case Addr_DataSym:
- VG_(message)(Vg_UserMsg,
- "%sAddress 0x%llx is %llu bytes "
- "inside data symbol \"%t\"%s",
- xpre,
- (ULong)a,
- (ULong)ai->Addr.DataSym.offset,
- ai->Addr.DataSym.name,
- xpost);
- break;
-
- case Addr_Variable:
- if (ai->Addr.Variable.descr1[0] != '\0')
- VG_(message)(Vg_UserMsg, "%s%s%s",
- xpre, ai->Addr.Variable.descr1, xpost);
- if (ai->Addr.Variable.descr2[0] != '\0')
- VG_(message)(Vg_UserMsg, "%s%s%s",
- xpre, ai->Addr.Variable.descr2, xpost);
- break;
-
- case Addr_SectKind:
- VG_(message)(Vg_UserMsg,
- "%sAddress 0x%llx is in the %t segment of %t%s",
- xpre,
- (ULong)a,
- VG_(pp_SectKind)(ai->Addr.SectKind.kind),
- ai->Addr.SectKind.objname,
- xpost);
- break;
-
- default:
- VG_(tool_panic)("mc_pp_AddrInfo");
- }
-}
-
-static const HChar* str_leak_lossmode ( Reachedness lossmode )
-{
- const HChar *loss = "?";
- switch (lossmode) {
- case Unreached: loss = "definitely lost"; break;
- case IndirectLeak: loss = "indirectly lost"; break;
- case Interior: loss = "possibly lost"; break;
- case Proper: loss = "still reachable"; break;
- }
- return loss;
-}
-
-static const HChar* xml_leak_kind ( Reachedness lossmode )
-{
- const HChar *loss = "?";
- switch (lossmode) {
- case Unreached: loss = "Leak_DefinitelyLost"; break;
- case IndirectLeak: loss = "Leak_IndirectlyLost"; break;
- case Interior: loss = "Leak_PossiblyLost"; break;
- case Proper: loss = "Leak_StillReachable"; break;
- }
- return loss;
-}
-
-static void mc_pp_msg( Char* xml_name, Error* err, const HChar* format, ... )
-{
- HChar* xpre = VG_(clo_xml) ? " <what>" : "";
- HChar* xpost = VG_(clo_xml) ? "</what>" : "";
- Char buf[256];
- va_list vargs;
-
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>%s</kind>", xml_name);
- // Stick xpre and xpost on the front and back of the format string.
- VG_(snprintf)(buf, 256, "%s%s%s", xpre, format, xpost);
- va_start(vargs, format);
- VG_(vmessage) ( Vg_UserMsg, buf, vargs );
- va_end(vargs);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-}
-
-static void mc_pp_origin ( ExeContext* ec, UInt okind )
-{
- HChar* src = NULL;
- HChar* xpre = VG_(clo_xml) ? " <what>" : " ";
- HChar* xpost = VG_(clo_xml) ? "</what>" : "";
- tl_assert(ec);
-
- switch (okind) {
- case MC_OKIND_STACK: src = " by a stack allocation"; break;
- case MC_OKIND_HEAP: src = " by a heap allocation"; break;
- case MC_OKIND_USER: src = " by a client request"; break;
- case MC_OKIND_UNKNOWN: src = ""; break;
- }
- tl_assert(src); /* guards against invalid 'okind' */
-
- if (VG_(clo_xml)) {
- VG_(message)(Vg_UserMsg, " <origin>");
- }
-
- VG_(message)(Vg_UserMsg, "%sUninitialised value was created%s%s",
- xpre, src, xpost);
- VG_(pp_ExeContext)( ec );
- if (VG_(clo_xml)) {
- VG_(message)(Vg_UserMsg, " </origin>");
- }
-}
-
-static void mc_pp_Error ( Error* err )
-{
- MC_Error* extra = VG_(get_error_extra)(err);
-
- switch (VG_(get_error_kind)(err)) {
- case Err_CoreMem: {
- /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
- /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
- signal handler frame. --njn */
- mc_pp_msg("CoreMemError", err,
- "%s contains unaddressable byte(s)",
- VG_(get_error_string)(err));
- break;
- }
-
- case Err_Value:
- any_value_errors = True;
- if (1 || extra->Err.Value.otag == 0) {
- mc_pp_msg("UninitValue", err,
- "Use of uninitialised value of size %d",
- extra->Err.Value.szB);
- } else {
- mc_pp_msg("UninitValue", err,
- "Use of uninitialised value of size %d (otag %u)",
- extra->Err.Value.szB, extra->Err.Value.otag);
- }
- if (extra->Err.Value.origin_ec)
- mc_pp_origin( extra->Err.Value.origin_ec,
- extra->Err.Value.otag & 3 );
- break;
-
- case Err_Cond:
- any_value_errors = True;
- if (1 || extra->Err.Cond.otag == 0) {
- mc_pp_msg("UninitCondition", err,
- "Conditional jump or move depends"
- " on uninitialised value(s)");
- } else {
- mc_pp_msg("UninitCondition", err,
- "Conditional jump or move depends"
- " on uninitialised value(s) (otag %u)",
- extra->Err.Cond.otag);
- }
- if (extra->Err.Cond.origin_ec)
- mc_pp_origin( extra->Err.Cond.origin_ec,
- extra->Err.Cond.otag & 3 );
- break;
-
- case Err_RegParam:
- any_value_errors = True;
- mc_pp_msg("SyscallParam", err,
- "Syscall param %s contains uninitialised byte(s)",
- VG_(get_error_string)(err));
- if (extra->Err.RegParam.origin_ec)
- mc_pp_origin( extra->Err.RegParam.origin_ec,
- extra->Err.RegParam.otag & 3 );
- break;
-
- case Err_MemParam:
- if (!extra->Err.MemParam.isAddrErr)
- any_value_errors = True;
- mc_pp_msg("SyscallParam", err,
- "Syscall param %s points to %s byte(s)",
- VG_(get_error_string)(err),
- ( extra->Err.MemParam.isAddrErr
- ? "unaddressable" : "uninitialised" ));
- mc_pp_AddrInfo(VG_(get_error_address)(err),
- &extra->Err.MemParam.ai, False);
- if (extra->Err.MemParam.origin_ec && !extra->Err.MemParam.isAddrErr)
- mc_pp_origin( extra->Err.MemParam.origin_ec,
- extra->Err.MemParam.otag & 3 );
- break;
-
- case Err_User:
- if (!extra->Err.User.isAddrErr)
- any_value_errors = True;
- mc_pp_msg("ClientCheck", err,
- "%s byte(s) found during client check request",
- ( extra->Err.User.isAddrErr
- ? "Unaddressable" : "Uninitialised" ));
- mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.User.ai,
- False);
- if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
- mc_pp_origin( extra->Err.User.origin_ec,
- extra->Err.User.otag & 3 );
- break;
-
- case Err_Free:
- mc_pp_msg("InvalidFree", err,
- "Invalid free() / delete / delete[]");
- mc_pp_AddrInfo(VG_(get_error_address)(err),
- &extra->Err.Free.ai, False);
- break;
-
- case Err_FreeMismatch:
- mc_pp_msg("MismatchedFree", err,
- "Mismatched free() / delete / delete []");
- mc_pp_AddrInfo(VG_(get_error_address)(err),
- &extra->Err.FreeMismatch.ai, False);
- break;
-
- case Err_Addr:
- if (extra->Err.Addr.isWrite) {
- mc_pp_msg("InvalidWrite", err,
- "Invalid write of size %d",
- extra->Err.Addr.szB);
- } else {
- 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);
- break;
-
- case Err_Jump:
- mc_pp_msg("InvalidJump", err,
- "Jump to the invalid address stated on the next line");
- mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Jump.ai,
- False);
- break;
-
- case Err_Overlap:
- if (extra->Err.Overlap.szB == 0)
- mc_pp_msg("Overlap", err,
- "Source and destination overlap in %s(%p, %p)",
- VG_(get_error_string)(err),
- extra->Err.Overlap.dst, extra->Err.Overlap.src);
- else
- mc_pp_msg("Overlap", err,
- "Source and destination overlap in %s(%p, %p, %d)",
- VG_(get_error_string)(err),
- extra->Err.Overlap.dst, extra->Err.Overlap.src,
- extra->Err.Overlap.szB);
- break;
-
- case Err_IllegalMempool:
- mc_pp_msg("InvalidMemPool", err,
- "Illegal memory pool address");
- mc_pp_AddrInfo(VG_(get_error_address)(err),
- &extra->Err.IllegalMempool.ai, False);
- break;
-
- case Err_Leak: {
- HChar* xpre = VG_(clo_xml) ? " <what>" : "";
- HChar* xpost = VG_(clo_xml) ? "</what>" : "";
- UInt n_this_record = extra->Err.Leak.n_this_record;
- UInt n_total_records = extra->Err.Leak.n_total_records;
- LossRecord* l = extra->Err.Leak.lossRecord;
-
- if (VG_(clo_xml)) {
- VG_(message)(Vg_UserMsg, " <kind>%t</kind>",
- xml_leak_kind(l->loss_mode));
- } else {
- VG_(message)(Vg_UserMsg, "");
- }
-
- if (l->indirect_bytes) {
- VG_(message)(Vg_UserMsg,
- "%s%,lu (%,lu direct, %,lu indirect) bytes in %,u blocks"
- " are %s in loss record %,u of %,u%s",
- xpre,
- l->total_bytes + l->indirect_bytes,
- l->total_bytes, l->indirect_bytes, l->num_blocks,
- str_leak_lossmode(l->loss_mode), n_this_record, n_total_records,
- xpost
- );
- if (VG_(clo_xml)) {
- // Nb: don't put commas in these XML numbers
- VG_(message)(Vg_UserMsg, " <leakedbytes>%lu</leakedbytes>",
- l->total_bytes + l->indirect_bytes);
- VG_(message)(Vg_UserMsg, " <leakedblocks>%u</leakedblocks>",
- l->num_blocks);
- }
- } else {
- VG_(message)(
- Vg_UserMsg,
- "%s%,lu bytes in %,u blocks are %s in loss record %,u of %,u%s",
- xpre,
- l->total_bytes, l->num_blocks,
- str_leak_lossmode(l->loss_mode), n_this_record, n_total_records,
- xpost
- );
- if (VG_(clo_xml)) {
- VG_(message)(Vg_UserMsg, " <leakedbytes>%d</leakedbytes>",
- l->total_bytes);
- VG_(message)(Vg_UserMsg, " <leakedblocks>%d</leakedblocks>",
- l->num_blocks);
- }
- }
- VG_(pp_ExeContext)(l->allocated_at);
- break;
- }
-
- default:
- VG_(printf)("Error:\n unknown Memcheck error code %d\n",
- VG_(get_error_kind)(err));
- VG_(tool_panic)("unknown error code in mc_pp_Error)");
- }
-}
-
-/*------------------------------------------------------------*/
-/*--- Recording errors ---*/
-/*------------------------------------------------------------*/
-
-/* These many bytes below %ESP are considered addressible if we're
- doing the --workaround-gcc296-bugs hack. */
-#define VG_GCC296_BUG_STACK_SLOP 1024
-
-/* Is this address within some small distance below %ESP? Used only
- for the --workaround-gcc296-bugs kludge. */
-static Bool is_just_below_ESP( Addr esp, Addr aa )
-{
- if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
- return True;
- else
- return False;
-}
-
-/* --- Called from generated and non-generated code --- */
-
-static void mc_record_address_error ( ThreadId tid, Addr a, Int szB,
- Bool isWrite )
-{
- MC_Error extra;
- Bool just_below_esp;
-
- if (in_ignored_range(a))
- return;
-
-# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
- /* AIX zero-page handling. On AIX, reads from page zero are,
- bizarrely enough, legitimate. Writes to page zero aren't,
- though. Since memcheck can't distinguish reads from writes, the
- best we can do is to 'act normal' and mark the A bits in the
- normal way as noaccess, but then hide any reads from that page
- that get reported here. */
- if ((!isWrite) && a >= 0 && a < 4096 && a+szB <= 4096)
- return;
-
- /* Appalling AIX hack. It suppresses reads done by glink
- fragments. Getting rid of this would require figuring out
- somehow where the referenced data areas are (and their
- sizes). */
- if ((!isWrite) && szB == sizeof(Word)) {
- UInt i1, i2;
- UInt* pc = (UInt*)VG_(get_IP)(tid);
- if (sizeof(Word) == 4) {
- i1 = 0x800c0000; /* lwz r0,0(r12) */
- i2 = 0x804c0004; /* lwz r2,4(r12) */
- } else {
- i1 = 0xe80c0000; /* ld r0,0(r12) */
- i2 = 0xe84c0008; /* ld r2,8(r12) */
- }
- if (pc[0] == i1 && pc[1] == i2) return;
- if (pc[0] == i2 && pc[-1] == i1) return;
- }
-# endif
-
- just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
-
- /* If this is caused by an access immediately below %ESP, and the
- user asks nicely, we just ignore it. */
- if (MC_(clo_workaround_gcc296_bugs) && just_below_esp)
- return;
-
- extra.Err.Addr.isWrite = isWrite;
- extra.Err.Addr.szB = szB;
- extra.Err.Addr.maybe_gcc = just_below_esp;
- extra.Err.Addr.ai.tag = Addr_Undescribed;
- VG_(maybe_record_error)( tid, Err_Addr, a, /*s*/NULL, &extra );
-}
-
-static void mc_record_value_error ( ThreadId tid, Int szB, UInt otag )
-{
- MC_Error extra;
- tl_assert( MC_(clo_mc_level) >= 2 );
- if (otag > 0)
- tl_assert( MC_(clo_mc_level) == 3 );
- extra.Err.Value.szB = szB;
- extra.Err.Value.otag = otag;
- extra.Err.Value.origin_ec = NULL; /* Filled in later */
- VG_(maybe_record_error)( tid, Err_Value, /*addr*/0, /*s*/NULL, &extra );
-}
-
-static void mc_record_cond_error ( ThreadId tid, UInt otag )
-{
- MC_Error extra;
- tl_assert( MC_(clo_mc_level) >= 2 );
- if (otag > 0)
- tl_assert( MC_(clo_mc_level) == 3 );
- extra.Err.Cond.otag = otag;
- extra.Err.Cond.origin_ec = NULL; /* Filled in later */
- VG_(maybe_record_error)( tid, Err_Cond, /*addr*/0, /*s*/NULL, &extra );
-}
-
-/* --- Called from non-generated code --- */
-
-/* This is for memory errors in pthread functions, as opposed to pthread API
- errors which are found by the core. */
-static void mc_record_core_mem_error ( ThreadId tid, Bool isAddrErr, Char* msg )
-{
- VG_(maybe_record_error)( tid, Err_CoreMem, /*addr*/0, msg, /*extra*/NULL );
-}
-
-static void mc_record_regparam_error ( ThreadId tid, Char* msg, UInt otag )
-{
- MC_Error extra;
- tl_assert(VG_INVALID_THREADID != tid);
- if (otag > 0)
- tl_assert( MC_(clo_mc_level) == 3 );
- extra.Err.RegParam.otag = otag;
- extra.Err.RegParam.origin_ec = NULL; /* Filled in later */
- VG_(maybe_record_error)( tid, Err_RegParam, /*addr*/0, msg, &extra );
-}
-
-static void mc_record_memparam_error ( ThreadId tid, Addr a,
- Bool isAddrErr, Char* msg, UInt otag )
-{
- MC_Error extra;
- tl_assert(VG_INVALID_THREADID != tid);
- if (!isAddrErr)
- tl_assert( MC_(clo_mc_level) >= 2 );
- if (otag != 0) {
- tl_assert( MC_(clo_mc_level) == 3 );
- tl_assert( !isAddrErr );
- }
- extra.Err.MemParam.isAddrErr = isAddrErr;
- extra.Err.MemParam.ai.tag = Addr_Undescribed;
- extra.Err.MemParam.otag = otag;
- extra.Err.MemParam.origin_ec = NULL; /* Filled in later */
- VG_(maybe_record_error)( tid, Err_MemParam, a, msg, &extra );
-}
-
-static void mc_record_jump_error ( ThreadId tid, Addr a )
-{
- MC_Error extra;
- tl_assert(VG_INVALID_THREADID != tid);
- extra.Err.Jump.ai.tag = Addr_Undescribed;
- VG_(maybe_record_error)( tid, Err_Jump, a, /*s*/NULL, &extra );
-}
-
-void MC_(record_free_error) ( ThreadId tid, Addr a )
-{
- MC_Error extra;
- tl_assert(VG_INVALID_THREADID != tid);
- extra.Err.Free.ai.tag = Addr_Undescribed;
- VG_(maybe_record_error)( tid, Err_Free, a, /*s*/NULL, &extra );
-}
-
-void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* mc )
-{
- MC_Error extra;
- AddrInfo* ai = &extra.Err.FreeMismatch.ai;
- tl_assert(VG_INVALID_THREADID != tid);
- ai->tag = Addr_Block;
- ai->Addr.Block.block_kind = Block_Mallocd; // Nb: Not 'Block_Freed'
- ai->Addr.Block.block_desc = "block";
- ai->Addr.Block.block_szB = mc->szB;
- ai->Addr.Block.rwoffset = 0;
- ai->Addr.Block.lastchange = mc->where;
- VG_(maybe_record_error)( tid, Err_FreeMismatch, mc->data, /*s*/NULL,
- &extra );
-}
-
-void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
-{
- MC_Error extra;
- tl_assert(VG_INVALID_THREADID != tid);
- extra.Err.IllegalMempool.ai.tag = Addr_Undescribed;
- VG_(maybe_record_error)( tid, Err_IllegalMempool, a, /*s*/NULL, &extra );
-}
-
-static void mc_record_overlap_error ( ThreadId tid, Char* function,
- Addr src, Addr dst, SizeT szB )
-{
- MC_Error extra;
- tl_assert(VG_INVALID_THREADID != tid);
- extra.Err.Overlap.src = src;
- extra.Err.Overlap.dst = dst;
- extra.Err.Overlap.szB = szB;
- VG_(maybe_record_error)(
- tid, Err_Overlap, /*addr*/0, /*s*/function, &extra );
-}
-
-Bool MC_(record_leak_error) ( ThreadId tid, UInt n_this_record,
- UInt n_total_records, LossRecord* lossRecord,
- Bool print_record )
-{
- MC_Error extra;
- extra.Err.Leak.n_this_record = n_this_record;
- extra.Err.Leak.n_total_records = n_total_records;
- extra.Err.Leak.lossRecord = lossRecord;
- return
- VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
- lossRecord->allocated_at, print_record,
- /*allow_GDB_attach*/False, /*count_error*/False );
-}
-
-static void mc_record_user_error ( ThreadId tid, Addr a,
- Bool isAddrErr, UInt otag )
-{
- MC_Error extra;
- if (otag != 0) {
- tl_assert(!isAddrErr);
- tl_assert( MC_(clo_mc_level) == 3 );
- }
- if (!isAddrErr) {
- tl_assert( MC_(clo_mc_level) >= 2 );
- }
- tl_assert(VG_INVALID_THREADID != tid);
- extra.Err.User.isAddrErr = isAddrErr;
- extra.Err.User.ai.tag = Addr_Undescribed;
- extra.Err.User.otag = otag;
- extra.Err.User.origin_ec = NULL; /* Filled in later */
- VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra );
-}
-
-/*------------------------------------------------------------*/
-/*--- Other error operations ---*/
-/*------------------------------------------------------------*/
-
-/* Compare error contexts, to detect duplicates. Note that if they
- are otherwise the same, the faulting addrs and associated rwoffsets
- are allowed to be different. */
-static Bool mc_eq_Error ( VgRes res, Error* e1, Error* e2 )
-{
- MC_Error* extra1 = VG_(get_error_extra)(e1);
- MC_Error* extra2 = VG_(get_error_extra)(e2);
-
- /* Guaranteed by calling function */
- tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
-
- switch (VG_(get_error_kind)(e1)) {
- case Err_CoreMem: {
- Char *e1s, *e2s;
- e1s = VG_(get_error_string)(e1);
- e2s = VG_(get_error_string)(e2);
- if (e1s == e2s) return True;
- if (VG_STREQ(e1s, e2s)) return True;
- return False;
- }
-
- case Err_RegParam:
- return VG_STREQ(VG_(get_error_string)(e1), VG_(get_error_string)(e2));
-
- // Perhaps we should also check the addrinfo.akinds for equality.
- // That would result in more error reports, but only in cases where
- // a register contains uninitialised bytes and points to memory
- // containing uninitialised bytes. Currently, the 2nd of those to be
- // detected won't be reported. That is (nearly?) always the memory
- // error, which is good.
- case Err_MemParam:
- if (!VG_STREQ(VG_(get_error_string)(e1),
- VG_(get_error_string)(e2))) return False;
- // fall through
- case Err_User:
- return ( extra1->Err.User.isAddrErr == extra2->Err.User.isAddrErr
- ? True : False );
-
- case Err_Free:
- case Err_FreeMismatch:
- case Err_Jump:
- case Err_IllegalMempool:
- case Err_Overlap:
- case Err_Cond:
- return True;
-
- case Err_Addr:
- return ( extra1->Err.Addr.szB == extra2->Err.Addr.szB
- ? True : False );
-
- case Err_Value:
- return ( extra1->Err.Value.szB == extra2->Err.Value.szB
- ? True : False );
-
- case Err_Leak:
- VG_(tool_panic)("Shouldn't get Err_Leak in mc_eq_Error,\n"
- "since it's handled with VG_(unique_error)()!");
-
- default:
- VG_(printf)("Error:\n unknown error code %d\n",
- VG_(get_error_kind)(e1));
- VG_(tool_panic)("unknown error code in mc_eq_Error");
- }
-}
-
-/* Function used when searching MC_Chunk lists */
-static Bool addr_is_in_MC_Chunk(MC_Chunk* mc, Addr a)
-{
- // Nb: this is not quite right! It assumes that the heap block has
- // a redzone of size MC_MALLOC_REDZONE_SZB. That's true for malloc'd
- // blocks, but not necessarily true for custom-alloc'd blocks. So
- // in some cases this could result in an incorrect description (eg.
- // saying "12 bytes after block A" when really it's within block B.
- // Fixing would require adding redzone size to MC_Chunks, though.
- return VG_(addr_is_in_block)( a, mc->data, mc->szB,
- MC_MALLOC_REDZONE_SZB );
-}
-
-// Forward declaration
-static Bool client_perm_maybe_describe( Addr a, AddrInfo* ai );
-
-
-/* Describe an address as best you can, for error messages,
- putting the result in ai. */
-static void describe_addr ( Addr a, /*OUT*/AddrInfo* ai )
-{
- MC_Chunk* mc;
- ThreadId tid;
- Addr stack_min, stack_max;
- VgSectKind sect;
-
- tl_assert(Addr_Undescribed == ai->tag);
-
- /* Perhaps it's a user-def'd block? */
- if (client_perm_maybe_describe( a, ai )) {
- return;
- }
- /* Search for a recently freed block which might bracket it. */
- mc = MC_(get_freed_list_head)();
- while (mc) {
- if (addr_is_in_MC_Chunk(mc, a)) {
- ai->tag = Addr_Block;
- ai->Addr.Block.block_kind = Block_Freed;
- ai->Addr.Block.block_desc = "block";
- ai->Addr.Block.block_szB = mc->szB;
- ai->Addr.Block.rwoffset = (Int)a - (Int)mc->data;
- ai->Addr.Block.lastchange = mc->where;
- return;
- }
- mc = mc->next;
- }
- /* Search for a currently malloc'd block which might bracket it. */
- VG_(HT_ResetIter)(MC_(malloc_list));
- while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
- if (addr_is_in_MC_Chunk(mc, a)) {
- ai->tag = Addr_Block;
- ai->Addr.Block.block_kind = Block_Mallocd;
- ai->Addr.Block.block_desc = "block";
- ai->Addr.Block.block_szB = mc->szB;
- ai->Addr.Block.rwoffset = (Int)a - (Int)mc->data;
- ai->Addr.Block.lastchange = mc->where;
- return;
- }
- }
- /* Perhaps the variable type/location data describes it? */
- tl_assert(sizeof(ai->Addr.Variable.descr1)
- == sizeof(ai->Addr.Variable.descr2));
- VG_(memset)( &ai->Addr.Variable.descr1,
- 0, sizeof(ai->Addr.Variable.descr1));
- VG_(memset)( &ai->Addr.Variable.descr2,
- 0, sizeof(ai->Addr.Variable.descr2));
- if (VG_(get_data_description)(
- &ai->Addr.Variable.descr1[0],
- &ai->Addr.Variable.descr2[0],
- sizeof(ai->Addr.Variable.descr1)-1,
- a )) {
- ai->tag = Addr_Variable;
- tl_assert( ai->Addr.Variable.descr1
- [ sizeof(ai->Addr.Variable.descr1)-1 ] == 0);
- tl_assert( ai->Addr.Variable.descr2
- [ sizeof(ai->Addr.Variable.descr2)-1 ] == 0);
- return;
- }
- /* Have a look at the low level data symbols - perhaps it's in
- there. */
- VG_(memset)( &ai->Addr.DataSym.name,
- 0, sizeof(ai->Addr.DataSym.name));
- if (VG_(get_datasym_and_offset)(
- a, &ai->Addr.DataSym.name[0],
- sizeof(ai->Addr.DataSym.name)-1,
- &ai->Addr.DataSym.offset )) {
- ai->tag = Addr_DataSym;
- tl_assert( ai->Addr.DataSym.name
- [ sizeof(ai->Addr.DataSym.name)-1 ] == 0);
- return;
- }
- /* Perhaps it's on a thread's stack? */
- VG_(thread_stack_reset_iter)(&tid);
- while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
- if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
- ai->tag = Addr_Stack;
- ai->Addr.Stack.tid = tid;
- return;
- }
- }
- /* last ditch attempt at classification */
- tl_assert( sizeof(ai->Addr.SectKind.objname) > 4 );
- VG_(memset)( &ai->Addr.SectKind.objname,
- 0, sizeof(ai->Addr.SectKind.objname));
- VG_(strcpy)( ai->Addr.SectKind.objname, "???" );
- sect = VG_(seginfo_sect_kind)( &ai->Addr.SectKind.objname[0],
- sizeof(ai->Addr.SectKind.objname)-1, a);
- if (sect != Vg_SectUnknown) {
- ai->tag = Addr_SectKind;
- ai->Addr.SectKind.kind = sect;
- tl_assert( ai->Addr.SectKind.objname
- [ sizeof(ai->Addr.SectKind.objname)-1 ] == 0);
- return;
- }
- /* Clueless ... */
- ai->tag = Addr_Unknown;
- return;
-}
-
-/* Fill in *origin_ec as specified by otag, or NULL it out if otag
- does not refer to a known origin. */
-static void update_origin ( /*OUT*/ExeContext** origin_ec,
- UInt otag )
-{
- UInt ecu = otag & ~3;
- *origin_ec = NULL;
- if (VG_(is_plausible_ECU)(ecu)) {
- *origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
- }
-}
-
-/* Updates the copy with address info if necessary (but not for all errors). */
-static UInt mc_update_extra( Error* err )
-{
- MC_Error* extra = VG_(get_error_extra)(err);
-
- switch (VG_(get_error_kind)(err)) {
- // These ones don't have addresses associated with them, and so don't
- // need any updating.
- case Err_CoreMem:
- //case Err_Value:
- //case Err_Cond:
- case Err_Overlap:
- // For Err_Leaks the returned size does not matter -- they are always
- // shown with VG_(unique_error)() so they 'extra' not copied. But
- // we make it consistent with the others.
- case Err_Leak:
- return sizeof(MC_Error);
-
- // For value errors, get the ExeContext corresponding to the
- // origin tag. Note that it is a kludge to assume that
- // a length-1 trace indicates a stack origin. FIXME.
- case Err_Value:
- update_origin( &extra->Err.Value.origin_ec,
- extra->Err.Value.otag );
- return sizeof(MC_Error);
- case Err_Cond:
- update_origin( &extra->Err.Cond.origin_ec,
- extra->Err.Cond.otag );
- return sizeof(MC_Error);
- case Err_RegParam:
- update_origin( &extra->Err.RegParam.origin_ec,
- extra->Err.RegParam.otag );
- return sizeof(MC_Error);
-
- // These ones always involve a memory address.
- case Err_Addr:
- describe_addr ( VG_(get_error_address)(err),
- &extra->Err.Addr.ai );
- return sizeof(MC_Error);
- case Err_MemParam:
- describe_addr ( VG_(get_error_address)(err),
- &extra->Err.MemParam.ai );
- update_origin( &extra->Err.MemParam.origin_ec,
- extra->Err.MemParam.otag );
- return sizeof(MC_Error);
- case Err_Jump:
- describe_addr ( VG_(get_error_address)(err),
- &extra->Err.Jump.ai );
- return sizeof(MC_Error);
- case Err_User:
- describe_addr ( VG_(get_error_address)(err),
- &extra->Err.User.ai );
- update_origin( &extra->Err.User.origin_ec,
- extra->Err.User.otag );
- return sizeof(MC_Error);
- case Err_Free:
- describe_addr ( VG_(get_error_address)(err),
- &extra->Err.Free.ai );
- return sizeof(MC_Error);
- case Err_IllegalMempool:
- describe_addr ( VG_(get_error_address)(err),
- &extra->Err.IllegalMempool.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
- // detected. However, the address may be part of a user block, and if so
- // we override the pre-determined description with a user block one.
- case Err_FreeMismatch: {
- tl_assert(extra && Block_Mallocd ==
- extra->Err.FreeMismatch.ai.Addr.Block.block_kind);
- (void)client_perm_maybe_describe( VG_(get_error_address)(err),
- &extra->Err.FreeMismatch.ai );
- return sizeof(MC_Error);
- }
-
- default: VG_(tool_panic)("mc_update_extra: bad errkind");
- }
+ MC_(record_regparam_error) ( tid, s, otag );
}
-/*------------------------------------------------------------*/
-/*--- Suppressions ---*/
-/*------------------------------------------------------------*/
-
-typedef
- enum {
- ParamSupp, // Bad syscall params
- UserSupp, // Errors arising from client-request checks
- CoreMemSupp, // Memory errors in core (pthread ops, signal handling)
-
- // Undefined value errors of given size
- Value1Supp, Value2Supp, Value4Supp, Value8Supp, Value16Supp,
-
- // Undefined value error in conditional.
- CondSupp,
-
- // Unaddressable read/write attempt at given size
- Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp, Addr16Supp,
-
- JumpSupp, // Jump to unaddressable target
- FreeSupp, // Invalid or mismatching free
- OverlapSupp, // Overlapping blocks in memcpy(), strcpy(), etc
- LeakSupp, // Something to be suppressed in a leak check.
- MempoolSupp, // Memory pool suppression.
- }
- MC_SuppKind;
-
-static Bool mc_recognised_suppression ( Char* name, Supp* su )
-{
- SuppKind skind;
-
- if (VG_STREQ(name, "Param")) skind = ParamSupp;
- else if (VG_STREQ(name, "User")) skind = UserSupp;
- else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
- else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
- else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
- else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
- else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
- else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
- else if (VG_STREQ(name, "Jump")) skind = JumpSupp;
- else if (VG_STREQ(name, "Free")) skind = FreeSupp;
- else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
- else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
- else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
- else if (VG_STREQ(name, "Cond")) skind = CondSupp;
- else if (VG_STREQ(name, "Value0")) skind = CondSupp; /* backwards compat */
- else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
- else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
- 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
- return False;
-
- VG_(set_supp_kind)(su, skind);
- return True;
-}
-
-static
-Bool mc_read_extra_suppression_info ( Int fd, Char* buf, Int nBuf, Supp *su )
-{
- Bool eof;
-
- if (VG_(get_supp_kind)(su) == ParamSupp) {
- eof = VG_(get_line) ( fd, buf, nBuf );
- if (eof) return False;
- VG_(set_supp_string)(su, VG_(strdup)(buf));
- }
- return True;
-}
-
-static Bool mc_error_matches_suppression(Error* err, Supp* su)
-{
- Int su_szB;
- MC_Error* extra = VG_(get_error_extra)(err);
- ErrorKind ekind = VG_(get_error_kind )(err);
-
- switch (VG_(get_supp_kind)(su)) {
- case ParamSupp:
- return ((ekind == Err_RegParam || ekind == Err_MemParam)
- && VG_STREQ(VG_(get_error_string)(err),
- VG_(get_supp_string)(su)));
-
- case UserSupp:
- return (ekind == Err_User);
-
- case CoreMemSupp:
- return (ekind == Err_CoreMem
- && VG_STREQ(VG_(get_error_string)(err),
- VG_(get_supp_string)(su)));
-
- case Value1Supp: su_szB = 1; goto value_case;
- case Value2Supp: su_szB = 2; goto value_case;
- case Value4Supp: su_szB = 4; goto value_case;
- case Value8Supp: su_szB = 8; goto value_case;
- case Value16Supp:su_szB =16; goto value_case;
- value_case:
- return (ekind == Err_Value && extra->Err.Value.szB == su_szB);
-
- case CondSupp:
- return (ekind == Err_Cond);
-
- case Addr1Supp: su_szB = 1; goto addr_case;
- case Addr2Supp: su_szB = 2; goto addr_case;
- case Addr4Supp: su_szB = 4; goto addr_case;
- case Addr8Supp: su_szB = 8; goto addr_case;
- case Addr16Supp:su_szB =16; goto addr_case;
- addr_case:
- return (ekind == Err_Addr && extra->Err.Addr.szB == su_szB);
-
- case JumpSupp:
- return (ekind == Err_Jump);
-
- case FreeSupp:
- return (ekind == Err_Free || ekind == Err_FreeMismatch);
-
- case OverlapSupp:
- return (ekind == Err_Overlap);
-
- case LeakSupp:
- return (ekind == Err_Leak);
-
- case MempoolSupp:
- return (ekind == Err_IllegalMempool);
-
- default:
- VG_(printf)("Error:\n"
- " unknown suppression type %d\n",
- VG_(get_supp_kind)(su));
- VG_(tool_panic)("unknown suppression type in "
- "MC_(error_matches_suppression)");
- }
-}
-
-static Char* mc_get_error_name ( Error* err )
-{
- switch (VG_(get_error_kind)(err)) {
- case Err_RegParam: return "Param";
- case Err_MemParam: return "Param";
- case Err_User: return "User";
- case Err_FreeMismatch: return "Free";
- case Err_IllegalMempool: return "Mempool";
- case Err_Free: return "Free";
- case Err_Jump: return "Jump";
- case Err_CoreMem: return "CoreMem";
- case Err_Overlap: return "Overlap";
- case Err_Leak: return "Leak";
- case Err_Cond: return "Cond";
- case Err_Addr: {
- MC_Error* extra = VG_(get_error_extra)(err);
- switch ( extra->Err.Addr.szB ) {
- case 1: return "Addr1";
- case 2: return "Addr2";
- case 4: return "Addr4";
- case 8: return "Addr8";
- case 16: return "Addr16";
- default: VG_(tool_panic)("unexpected size for Addr");
- }
- }
- case Err_Value: {
- MC_Error* extra = VG_(get_error_extra)(err);
- switch ( extra->Err.Value.szB ) {
- case 1: return "Value1";
- case 2: return "Value2";
- case 4: return "Value4";
- case 8: return "Value8";
- case 16: return "Value16";
- default: VG_(tool_panic)("unexpected size for Value");
- }
- }
- default: VG_(tool_panic)("get_error_name: unexpected type");
- }
-}
-
-static void mc_print_extra_suppression_info ( Error* err )
-{
- ErrorKind ekind = VG_(get_error_kind )(err);
- if (Err_RegParam == ekind || Err_MemParam == ekind) {
- VG_(printf)(" %s\n", VG_(get_error_string)(err));
- }
-}
/*------------------------------------------------------------*/
/*--- Functions called directly from generated code: ---*/
@@ -5294,54 +4030,54 @@ void MC_(helperc_STOREV8) ( Addr a, UWord vbits8 )
/* Call these ones when an origin is available ... */
VG_REGPARM(1)
void MC_(helperc_value_check0_fail_w_o) ( UWord origin ) {
- mc_record_cond_error ( VG_(get_running_tid)(), (UInt)origin );
+ MC_(record_cond_error) ( VG_(get_running_tid)(), (UInt)origin );
}
VG_REGPARM(1)
void MC_(helperc_value_check1_fail_w_o) ( UWord origin ) {
- mc_record_value_error ( VG_(get_running_tid)(), 1, (UInt)origin );
+ MC_(record_value_error) ( VG_(get_running_tid)(), 1, (UInt)origin );
}
VG_REGPARM(1)
void MC_(helperc_value_check4_fail_w_o) ( UWord origin ) {
- mc_record_value_error ( VG_(get_running_tid)(), 4, (UInt)origin );
+ MC_(record_value_error) ( VG_(get_running_tid)(), 4, (UInt)origin );
}
VG_REGPARM(1)
void MC_(helperc_value_check8_fail_w_o) ( UWord origin ) {
- mc_record_value_error ( VG_(get_running_tid)(), 8, (UInt)origin );
+ MC_(record_value_error) ( VG_(get_running_tid)(), 8, (UInt)origin );
}
VG_REGPARM(2)
void MC_(helperc_value_checkN_fail_w_o) ( HWord sz, UWord origin ) {
- mc_record_value_error ( VG_(get_running_tid)(), (Int)sz, (UInt)origin );
+ MC_(record_value_error) ( VG_(get_running_tid)(), (Int)sz, (UInt)origin );
}
/* ... and these when an origin isn't available. */
VG_REGPARM(0)
void MC_(helperc_value_check0_fail_no_o) ( void ) {
- mc_record_cond_error ( VG_(get_running_tid)(), 0/*origin*/ );
+ MC_(record_cond_error) ( VG_(get_running_tid)(), 0/*origin*/ );
}
VG_REGPARM(0)
void MC_(helperc_value_check1_fail_no_o) ( void ) {
- mc_record_value_error ( VG_(get_running_tid)(), 1, 0/*origin*/ );
+ MC_(record_value_error) ( VG_(get_running_tid)(), 1, 0/*origin*/ );
}
VG_REGPARM(0)
void MC_(helperc_value_check4_fail_no_o) ( void ) {
- mc_record_value_error ( VG_(get_running_tid)(), 4, 0/*origin*/ );
+ MC_(record_value_error) ( VG_(get_running_tid)(), 4, 0/*origin*/ );
}
VG_REGPARM(0)
void MC_(helperc_value_check8_fail_no_o) ( void ) {
- mc_record_value_error ( VG_(get_running_tid)(), 8, 0/*origin*/ );
+ MC_(record_value_error) ( VG_(get_running_tid)(), 8, 0/*origin*/ );
}
VG_REGPARM(1)
void MC_(helperc_value_checkN_fail_no_o) ( HWord sz ) {
- mc_record_value_error ( VG_(get_running_tid)(), (Int)sz, 0/*origin*/ );
+ MC_(record_value_error) ( VG_(get_running_tid)(), (Int)sz, 0/*origin*/ );
}
@@ -5413,7 +4149,7 @@ Bool mc_is_within_valid_secondary ( Addr a )
{
SecMap* sm = maybe_get_secmap_for ( a );
if (sm == NULL || sm == &sm_distinguished[SM_DIST_NOACCESS]
- || in_ignored_range(a)) {
+ || MC_(in_ignored_range)(a)) {
/* Definitely not in use. */
return False;
} else {
@@ -5434,7 +4170,7 @@ Bool mc_is_valid_aligned_word ( Addr a )
tl_assert(VG_IS_8_ALIGNED(a));
}
if (is_mem_defined( a, sizeof(UWord), NULL, NULL) == MC_Ok
- && !in_ignored_range(a)) {
+ && !MC_(in_ignored_range)(a)) {
return True;
} else {
return False;
@@ -5746,7 +4482,7 @@ static void mc_print_debug_usage(void)
/*------------------------------------------------------------*/
-/*--- Client requests ---*/
+/*--- Client blocks ---*/
/*------------------------------------------------------------*/
/* Client block management:
@@ -5761,14 +4497,7 @@ static void mc_print_debug_usage(void)
An unused block has start == size == 0
*/
-typedef
- struct {
- Addr start;
- SizeT size;
- ExeContext* where;
- Char* desc;
- }
- CGenBlock;
+/* type CGenBlock is defined in mc_include.h */
/* This subsystem is self-initialising. */
static UInt cgb_size = 0;
@@ -5782,6 +4511,15 @@ static UInt cgb_discards = 0; /* Number of discards. */
static UInt cgb_search = 0; /* Number of searches. */
+/* Get access to the client block array. */
+void MC_(get_ClientBlock_array)( /*OUT*/CGenBlock** blocks,
+ /*OUT*/UWord* nBlocks )
+{
+ *blocks = cgbs;
+ *nBlocks = cgb_used;
+}
+
+
static
Int alloc_client_block ( void )
{
@@ -5830,54 +4568,10 @@ static void show_client_block_stats ( void )
);
}
-static Bool client_perm_maybe_describe( Addr a, AddrInfo* ai )
-{
- UInt i;
- /* Perhaps it's a general block ? */
- for (i = 0; i < cgb_used; i++) {
- if (cgbs[i].start == 0 && cgbs[i].size == 0)
- continue;
- // Use zero as the redzone for client blocks.
- if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
- /* OK - maybe it's a mempool, too? */
- MC_Mempool* mp = VG_(HT_lookup)(MC_(mempool_list),
- (UWord)cgbs[i].start);
- if (mp != NULL) {
- if (mp->chunks != NULL) {
- MC_Chunk* mc;
- VG_(HT_ResetIter)(mp->chunks);
- while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
- if (addr_is_in_MC_Chunk(mc, a)) {
- ai->tag = Addr_Block;
- ai->Addr.Block.block_kind = Block_MempoolChunk;
- ai->Addr.Block.block_desc = "block";
- ai->Addr.Block.block_szB = mc->szB;
- ai->Addr.Block.rwoffset = (Int)a - (Int)mc->data;
- ai->Addr.Block.lastchange = mc->where;
- return True;
- }
- }
- }
- ai->tag = Addr_Block;
- ai->Addr.Block.block_kind = Block_Mempool;
- ai->Addr.Block.block_desc = "mempool";
- ai->Addr.Block.block_szB = cgbs[i].size;
- ai->Addr.Block.rwoffset = (Int)(a) - (Int)(cgbs[i].start);
- ai->Addr.Block.lastchange = cgbs[i].where;
- return True;
- }
- ai->tag = Addr_Block;
- ai->Addr.Block.block_kind = Block_UserG;
- ai->Addr.Block.block_desc = cgbs[i].desc;
- ai->Addr.Block.block_szB = cgbs[i].size;
- ai->Addr.Block.rwoffset = (Int)(a) - (Int)(cgbs[i].start);
- ai->Addr.Block.lastchange = cgbs[i].where;
- return True;
- }
- }
- return False;
-}
+/*------------------------------------------------------------*/
+/*--- Client requests ---*/
+/*------------------------------------------------------------*/
static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
{
@@ -5886,23 +4580,23 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
Addr bad_addr;
if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
- && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
- && VG_USERREQ__FREELIKE_BLOCK != arg[0]
- && VG_USERREQ__CREATE_MEMPOOL != arg[0]
- && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
- && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
- && VG_USERREQ__MEMPOOL_FREE != arg[0]
- && VG_USERREQ__MEMPOOL_TRIM != arg[0]
- && VG_USERREQ__MOVE_MEMPOOL != arg[0]
- && VG_USERREQ__MEMPOOL_CHANGE != arg[0]
- && VG_USERREQ__MEMPOOL_EXISTS != arg[0])
+ && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
+ && VG_USERREQ__FREELIKE_BLOCK != arg[0]
+ && VG_USERREQ__CREATE_MEMPOOL != arg[0]
+ && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
+ && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
+ && VG_USERREQ__MEMPOOL_FREE != arg[0]
+ && VG_USERREQ__MEMPOOL_TRIM != arg[0]
+ && VG_USERREQ__MOVE_MEMPOOL != arg[0]
+ && VG_USERREQ__MEMPOOL_CHANGE != arg[0]
+ && VG_USERREQ__MEMPOOL_EXISTS != arg[0])
return False;
switch (arg[0]) {
case VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE:
ok = is_mem_addressable ( arg[1], arg[2], &bad_addr );
if (!ok)
- mc_record_user_error ( tid, bad_addr, /*isAddrErr*/True, 0 );
+ MC_(record_user_error) ( tid, bad_addr, /*isAddrErr*/True, 0 );
*ret = ok ? (UWord)NULL : bad_addr;
break;
@@ -5911,9 +4605,9 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
UInt otag = 0;
res = is_mem_defined ( arg[1], arg[2], &bad_addr, &otag );
if (MC_AddrErr == res)
- mc_record_user_error ( tid, bad_addr, /*isAddrErr*/True, 0 );
+ MC_(record_user_error) ( tid, bad_addr, /*isAddrErr*/True, 0 );
else if (MC_ValueErr == res)
- mc_record_user_error ( tid, bad_addr, /*isAddrErr*/False, otag );
+ MC_(record_user_error) ( tid, bad_addr, /*isAddrErr*/False, otag );
*ret = ( res==MC_Ok ? (UWord)NULL : bad_addr );
break;
}
@@ -5929,7 +4623,8 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
break;
case VG_USERREQ__MAKE_MEM_UNDEFINED:
- make_mem_undefined_w_tid_and_okind ( arg[1], arg[2], tid, MC_OKIND_USER );
+ make_mem_undefined_w_tid_and_okind ( arg[1], arg[2], tid,
+ MC_OKIND_USER );
*ret = -1;
break;
@@ -6018,7 +4713,7 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
Addr dst = (Addr) arg[2];
Addr src = (Addr) arg[3];
SizeT len = (SizeT)arg[4];
- mc_record_overlap_error(tid, s, src, dst, len);
+ MC_(record_overlap_error)(tid, s, src, dst, len);
return True;
}
@@ -6474,7 +5169,6 @@ static void ocache_sarp_Clear_Origins ( Addr a, UWord len ) {
/*--- Setup and finalisation ---*/
/*------------------------------------------------------------*/
-
static void mc_post_clo_init ( void )
{
/* If we've been asked to emit XML, mash around various other
@@ -6542,7 +5236,7 @@ static void mc_fini ( Int exitcode )
}
- if (any_value_errors && !VG_(clo_xml) && VG_(clo_verbosity) >= 1
+ if (MC_(any_value_errors) && !VG_(clo_xml) && VG_(clo_verbosity) >= 1
&& MC_(clo_mc_level) == 2) {
VG_(message)(Vg_UserMsg,
"Use --track-origins=yes to see where "
@@ -6663,15 +5357,15 @@ static void mc_pre_clo_init(void)
VG_(needs_core_errors) ();
- VG_(needs_tool_errors) (mc_eq_Error,
- mc_pp_Error,
+ VG_(needs_tool_errors) (MC_(eq_Error),
+ MC_(pp_Error),
True,/*show TIDs for errors*/
- mc_update_extra,
- mc_recognised_suppression,
- mc_read_extra_suppression_info,
- mc_error_matches_suppression,
- mc_get_error_name,
- mc_print_extra_suppression_info);
+ MC_(update_Error_extra),
+ MC_(is_recognised_suppression),
+ MC_(read_extra_suppression_info),
+ MC_(error_matches_suppression),
+ MC_(get_error_name),
+ MC_(print_extra_suppression_info));
VG_(needs_libc_freeres) ();
VG_(needs_command_line_options)(mc_process_cmd_line_options,
mc_print_usage,
@@ -6765,5 +5459,5 @@ static void mc_pre_clo_init(void)
VG_DETERMINE_INTERFACE_VERSION(mc_pre_clo_init)
/*--------------------------------------------------------------------*/
-/*--- end ---*/
+/*--- end mc_main.c ---*/
/*--------------------------------------------------------------------*/