[compiler-rt] r223233 - [msan] Change the way origin ids are built.
Evgeniy Stepanov
eugeni.stepanov at gmail.com
Wed Dec 3 05:58:41 PST 2014
Author: eugenis
Date: Wed Dec 3 07:58:40 2014
New Revision: 223233
URL: http://llvm.org/viewvc/llvm-project?rev=223233&view=rev
Log:
[msan] Change the way origin ids are built.
Previously, all origin ids were "chained" origins, i.e values of
ChainedOriginDepot. This added a level of indirection for simple
stack and heap allocation, which were represented as chains of
length 1. This costs both RAM and CPU, but provides a joined 2**29
origin id space. It also made function (any instrumented function)
entry non-async-signal-safe, but that does not really matter because
memory stores in track-origins=2 mode are not async-signal-safe anyway.
With this change, the type of the origin is encoded in origin id.
See comment in msan_origin.h for more details. This reduces chained and stack
origin id range to 2**28 each, but leaves extra 2**31 for heap origins.
This change should not have any user-visible effects.
Modified:
compiler-rt/trunk/lib/msan/msan.cc
compiler-rt/trunk/lib/msan/msan_allocator.cc
compiler-rt/trunk/lib/msan/msan_chained_origin_depot.cc
compiler-rt/trunk/lib/msan/msan_interceptors.cc
compiler-rt/trunk/lib/msan/msan_origin.h
compiler-rt/trunk/lib/msan/msan_report.cc
Modified: compiler-rt/trunk/lib/msan/msan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=223233&r1=223232&r2=223233&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.cc (original)
+++ compiler-rt/trunk/lib/msan/msan.cc Wed Dec 3 07:58:40 2014
@@ -205,10 +205,10 @@ void PrintWarningWithOrigin(uptr pc, upt
GET_FATAL_STACK_TRACE_PC_BP(pc, bp);
u32 report_origin =
- (__msan_get_track_origins() && Origin(origin).isValid()) ? origin : 0;
+ (__msan_get_track_origins() && Origin::isValidId(origin)) ? origin : 0;
ReportUMR(&stack, report_origin);
- if (__msan_get_track_origins() && !Origin(origin).isValid()) {
+ if (__msan_get_track_origins() && !Origin::isValidId(origin)) {
Printf(
" ORIGIN: invalid (%x). Might be a bug in MemorySanitizer origin "
"tracking.\n This could still be a bug in your code, too!\n",
@@ -258,32 +258,9 @@ u32 ChainOrigin(u32 id, StackTrace *stac
if (t && t->InSignalHandler())
return id;
- Origin o(id);
- int depth = o.depth();
- // 0 means unlimited depth.
- if (flags()->origin_history_size > 0 && depth > 0) {
- if (depth >= flags()->origin_history_size) {
- return id;
- } else {
- ++depth;
- }
- }
-
- StackDepotHandle h = StackDepotPut_WithHandle(*stack);
- if (!h.valid()) return id;
-
- if (flags()->origin_history_per_stack_limit > 0) {
- int use_count = h.use_count();
- if (use_count > flags()->origin_history_per_stack_limit) return id;
- }
-
- u32 chained_id;
- bool inserted = ChainedOriginDepotPut(h.id(), o.id(), &chained_id);
-
- if (inserted && flags()->origin_history_per_stack_limit > 0)
- h.inc_use_count_unsafe();
-
- return Origin(chained_id, depth).raw_id();
+ Origin o = Origin::FromRawId(id);
+ Origin chained = Origin::CreateChainedOrigin(o, stack);
+ return chained.raw_id();
}
} // namespace __msan
@@ -542,14 +519,14 @@ void __msan_set_alloca_origin4(void *a,
CHECK_LT(idx, kNumStackOriginDescrs);
StackOriginDescr[idx] = descr + 4;
StackOriginPC[idx] = pc;
- ChainedOriginDepotPut(idx, Origin::kStackRoot, &id);
+ id = Origin::CreateStackOrigin(idx).raw_id();
*id_ptr = id;
if (print)
Printf("First time: idx=%d id=%d %s %p \n", idx, id, descr + 4, pc);
}
if (print)
Printf("__msan_set_alloca_origin: descr=%s id=%x\n", descr + 4, id);
- __msan_set_origin(a, size, Origin(id, 1).raw_id());
+ __msan_set_origin(a, size, id);
}
u32 __msan_chain_origin(u32 id) {
Modified: compiler-rt/trunk/lib/msan/msan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.cc?rev=223233&r1=223232&r2=223233&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_allocator.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_allocator.cc Wed Dec 3 07:58:40 2014
@@ -14,10 +14,8 @@
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_allocator_interface.h"
-#include "sanitizer_common/sanitizer_stackdepot.h"
#include "msan.h"
#include "msan_allocator.h"
-#include "msan_chained_origin_depot.h"
#include "msan_origin.h"
#include "msan_thread.h"
@@ -114,11 +112,8 @@ static void *MsanAllocate(StackTrace *st
} else if (flags()->poison_in_malloc) {
__msan_poison(allocated, size);
if (__msan_get_track_origins()) {
- u32 stack_id = StackDepotPut(*stack);
- CHECK(stack_id);
- u32 id;
- ChainedOriginDepotPut(stack_id, Origin::kHeapRoot, &id);
- __msan_set_origin(allocated, size, Origin(id, 1).raw_id());
+ Origin o = Origin::CreateHeapOrigin(stack);
+ __msan_set_origin(allocated, size, o.raw_id());
}
}
MSAN_MALLOC_HOOK(allocated, size);
@@ -137,11 +132,8 @@ void MsanDeallocate(StackTrace *stack, v
if (flags()->poison_in_free) {
__msan_poison(p, size);
if (__msan_get_track_origins()) {
- u32 stack_id = StackDepotPut(*stack);
- CHECK(stack_id);
- u32 id;
- ChainedOriginDepotPut(stack_id, Origin::kHeapRoot, &id);
- __msan_set_origin(p, size, Origin(id, 1).raw_id());
+ Origin o = Origin::CreateHeapOrigin(stack);
+ __msan_set_origin(p, size, o.raw_id());
}
}
MsanThread *t = GetCurrentThread();
Modified: compiler-rt/trunk/lib/msan/msan_chained_origin_depot.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_chained_origin_depot.cc?rev=223233&r1=223232&r2=223233&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_chained_origin_depot.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_chained_origin_depot.cc Wed Dec 3 07:58:40 2014
@@ -94,8 +94,7 @@ struct ChainedOriginDepotNode {
typedef Handle handle_type;
};
-// kTabSizeLog = 22 => 32Mb static storage for bucket pointers.
-static StackDepotBase<ChainedOriginDepotNode, 3, 20> chainedOriginDepot;
+static StackDepotBase<ChainedOriginDepotNode, 4, 20> chainedOriginDepot;
StackDepotStats *ChainedOriginDepotGetStats() {
return chainedOriginDepot.GetStats();
Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=223233&r1=223232&r2=223233&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Wed Dec 3 07:58:40 2014
@@ -956,10 +956,8 @@ void __msan_allocated_memory(const void*
if (flags()->poison_in_malloc)
__msan_poison(data, size);
if (__msan_get_track_origins()) {
- u32 stack_id = StackDepotPut(stack);
- u32 id;
- ChainedOriginDepotPut(stack_id, Origin::kHeapRoot, &id);
- __msan_set_origin(data, size, Origin(id, 1).raw_id());
+ Origin o = Origin::CreateHeapOrigin(&stack);
+ __msan_set_origin(data, size, o.raw_id());
}
}
Modified: compiler-rt/trunk/lib/msan/msan_origin.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_origin.h?rev=223233&r1=223232&r2=223233&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_origin.h (original)
+++ compiler-rt/trunk/lib/msan/msan_origin.h Wed Dec 3 07:58:40 2014
@@ -12,6 +12,9 @@
#ifndef MSAN_ORIGIN_H
#define MSAN_ORIGIN_H
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "msan_chained_origin_depot.h"
+
namespace __msan {
// Origin handling.
@@ -20,9 +23,22 @@ namespace __msan {
// the program and describes, more or less exactly, how this memory came to be
// uninitialized.
//
-// Origin ids are values of ChainedOriginDepot, which is a mapping of (stack_id,
-// prev_id) -> id, where
-// * stack_id describes an event in the program, usually a memory store.
+// There are 3 kinds of origin ids:
+// 1xxx xxxx xxxx xxxx heap origin id
+// 0000 xxxx xxxx xxxx stack origin id
+// 0zzz xxxx xxxx xxxx chained origin id
+//
+// Heap origin id describes a heap memory allocation and contains (in the xxx
+// part) a value of StackDepot.
+//
+// Stack origin id describes a stack memory allocation and contains (in the xxx
+// part) an index into StackOriginDescr and StackOriginPC. We don't store a
+// stack trace for such origins for performance reasons.
+//
+// Chained origin id describes an event of storing an uninitialized value to
+// memory. The xxx part is a value of ChainedOriginDepot, which is a mapping of
+// (stack_id, prev_id) -> id, where
+// * stack_id describes the event.
// StackDepot keeps a mapping between those and corresponding stack traces.
// * prev_id is another origin id that describes the earlier part of the
// uninitialized value history.
@@ -33,43 +49,119 @@ namespace __msan {
// points in value history marked with origin ids, and edges are events that are
// marked with stack_id.
//
-// There are 2 special root origin ids:
-// * kHeapRoot - an origin with prev_id == kHeapRoot describes an event of
-// allocating memory from heap.
-// * kStackRoot - an origin with prev_id == kStackRoot describes an event of
-// allocating memory from stack (i.e. on function entry).
-// Note that ChainedOriginDepot does not store any node for kHeapRoot or
-// kStackRoot. These are just special id values.
-//
-// Three highest bits of origin id are used to store the length (or depth) of
-// the origin chain. Special depth value of 0 means unlimited.
+// The "zzz" bits of chained origin id are used to store the length (or depth)
+// of the origin chain.
class Origin {
public:
- static const int kDepthBits = 3;
- static const int kDepthShift = 32 - kDepthBits;
- static const u32 kIdMask = ((u32)-1) >> (32 - kDepthShift);
- static const u32 kDepthMask = ~kIdMask;
+ static bool isValidId(u32 id) { return id != 0 && id != (u32)-1; }
- static const int kMaxDepth = (1 << kDepthBits) - 1;
+ u32 raw_id() const { return raw_id_; }
+ bool isHeapOrigin() const {
+ // 1xxx xxxx xxxx xxxx
+ return raw_id_ >> kHeapShift == 0;
+ }
+ bool isStackOrigin() const {
+ // 1000 xxxx xxxx xxxx
+ return (raw_id_ >> kDepthShift) == (1 << kDepthBits);
+ }
+ bool isChainedOrigin() const {
+ // 1zzz xxxx xxxx xxxx, zzz != 000
+ return (raw_id_ >> kDepthShift) > (1 << kDepthBits);
+ }
+ u32 getChainedId() const {
+ CHECK(isChainedOrigin());
+ return raw_id_ & kChainedIdMask;
+ }
+ u32 getStackId() const {
+ CHECK(isStackOrigin());
+ return raw_id_ & kChainedIdMask;
+ }
+ u32 getHeapId() const {
+ CHECK(isHeapOrigin());
+ return raw_id_ & kHeapIdMask;
+ }
- static const u32 kHeapRoot = (u32)-1;
- static const u32 kStackRoot = (u32)-2;
+ // Returns the next origin in the chain and the current stack trace.
+ Origin getNextChainedOrigin(StackTrace *stack) const {
+ CHECK(isChainedOrigin());
+ u32 prev_id;
+ u32 stack_id = ChainedOriginDepotGet(getChainedId(), &prev_id);
+ *stack = StackDepotGet(stack_id);
+ return Origin(prev_id);
+ }
- explicit Origin(u32 raw_id) : raw_id_(raw_id) {}
- Origin(u32 id, u32 depth) : raw_id_((depth << kDepthShift) | id) {
- CHECK_EQ(this->depth(), depth);
- CHECK_EQ(this->id(), id);
+ StackTrace getStackTraceForHeapOrigin() const {
+ return StackDepotGet(getHeapId());
+ }
+
+ static Origin CreateStackOrigin(u32 id) {
+ CHECK((id & kStackIdMask) == id);
+ return Origin((1 << kHeapShift) | id);
+ }
+
+ static Origin CreateHeapOrigin(StackTrace *stack) {
+ u32 stack_id = StackDepotPut(*stack);
+ CHECK(stack_id);
+ CHECK((stack_id & kHeapIdMask) == stack_id);
+ return Origin(stack_id);
+ }
+
+ static Origin CreateChainedOrigin(Origin prev, StackTrace *stack) {
+ int depth = prev.isChainedOrigin() ? prev.depth() : 0;
+ // depth is the length of the chain minus 1.
+ // origin_history_size of 0 means unlimited depth.
+ if (flags()->origin_history_size > 0) {
+ if (depth + 1 >= flags()->origin_history_size) {
+ return prev;
+ } else {
+ ++depth;
+ CHECK(depth < (1 << kDepthBits));
+ }
+ }
+
+ StackDepotHandle h = StackDepotPut_WithHandle(*stack);
+ if (!h.valid()) return prev;
+
+ if (flags()->origin_history_per_stack_limit > 0) {
+ int use_count = h.use_count();
+ if (use_count > flags()->origin_history_per_stack_limit) return prev;
+ }
+
+ u32 chained_id;
+ bool inserted = ChainedOriginDepotPut(h.id(), prev.raw_id(), &chained_id);
+ CHECK((chained_id & kChainedIdMask) == chained_id);
+
+ if (inserted && flags()->origin_history_per_stack_limit > 0)
+ h.inc_use_count_unsafe();
+
+ return Origin((1 << kHeapShift) | (depth << kDepthShift) | chained_id);
+ }
+
+ static Origin FromRawId(u32 id) {
+ return Origin(id);
}
- int depth() const { return raw_id_ >> kDepthShift; }
- u32 id() const { return raw_id_ & kIdMask; }
- u32 raw_id() const { return raw_id_; }
- bool isStackRoot() const { return raw_id_ == kStackRoot; }
- bool isHeapRoot() const { return raw_id_ == kHeapRoot; }
- bool isValid() const { return raw_id_ != 0 && raw_id_ != (u32)-1; }
private:
+ static const int kDepthBits = 3;
+ static const int kDepthShift = 32 - kDepthBits - 1;
+
+ static const int kHeapShift = 31;
+ static const u32 kChainedIdMask = ((u32)-1) >> (32 - kDepthShift);
+ static const u32 kStackIdMask = ((u32)-1) >> (32 - kDepthShift);
+ static const u32 kHeapIdMask = ((u32)-1) >> (32 - kHeapShift);
+
u32 raw_id_;
+
+ explicit Origin(u32 raw_id) : raw_id_(raw_id) {}
+
+ int depth() const {
+ CHECK(isChainedOrigin());
+ return (raw_id_ >> kDepthShift) & ((1 << kDepthBits) - 1);
+ }
+
+ public:
+ static const int kMaxDepth = (1 << kDepthBits) - 1;
};
} // namespace __msan
Modified: compiler-rt/trunk/lib/msan/msan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_report.cc?rev=223233&r1=223232&r2=223233&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_report.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_report.cc Wed Dec 3 07:58:40 2014
@@ -61,34 +61,23 @@ static void DescribeStackOrigin(const ch
static void DescribeOrigin(u32 id) {
VPrintf(1, " raw origin id: %d\n", id);
Decorator d;
- while (true) {
- Origin o(id);
- if (!o.isValid()) {
- Printf(" %sinvalid origin id(%d)%s\n", d.Warning(), id, d.End());
- break;
- }
- u32 prev_id;
- u32 stack_id = ChainedOriginDepotGet(o.id(), &prev_id);
- Origin prev_o(prev_id);
-
- if (prev_o.isStackRoot()) {
- uptr pc;
- const char *so = GetStackOriginDescr(stack_id, &pc);
- DescribeStackOrigin(so, pc);
- break;
- } else if (prev_o.isHeapRoot()) {
- Printf(" %sUninitialized value was created by a heap allocation%s\n",
- d.Origin(), d.End());
- StackDepotGet(stack_id).Print();
- break;
- } else {
- // chained origin
- // FIXME: copied? modified? passed through? observed?
- Printf(" %sUninitialized value was stored to memory at%s\n", d.Origin(),
- d.End());
- StackDepotGet(stack_id).Print();
- id = prev_id;
- }
+ Origin o = Origin::FromRawId(id);
+ while (o.isChainedOrigin()) {
+ StackTrace stack;
+ o = o.getNextChainedOrigin(&stack);
+ Printf(" %sUninitialized value was stored to memory at%s\n", d.Origin(),
+ d.End());
+ stack.Print();
+ }
+ if (o.isStackOrigin()) {
+ uptr pc;
+ const char *so = GetStackOriginDescr(o.getStackId(), &pc);
+ DescribeStackOrigin(so, pc);
+ } else {
+ StackTrace stack = o.getStackTraceForHeapOrigin();
+ Printf(" %sUninitialized value was created by a heap allocation%s\n",
+ d.Origin(), d.End());
+ stack.Print();
}
}
More information about the llvm-commits
mailing list