Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(793)

Unified Diff: runtime/vm/profiler_service.cc

Issue 2939853002: [fuchsia] Make profile processing resilient to bogus overlaps from dladdr. (Closed)
Patch Set: verify too slow to leave on Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/profiler_service.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/profiler_service.cc
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index f245ed5f29657d2f5ac8d176c217fdc1f26b4ba9..b89ca0a4549b0eab428e230965ab8c7aa3be26d9 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -302,10 +302,31 @@ ProfileCode::ProfileCode(Kind kind,
address_ticks_(0) {}
-void ProfileCode::AdjustExtent(uword start, uword end) {
+void ProfileCode::TruncateLower(uword start) {
+ if (start > start_) {
+ start_ = start;
+ }
+ ASSERT(start_ < end_);
+}
+
+
+void ProfileCode::TruncateUpper(uword end) {
+ if (end < end_) {
+ end_ = end;
+ }
+ ASSERT(start_ < end_);
+}
+
+
+void ProfileCode::ExpandLower(uword start) {
if (start < start_) {
start_ = start;
}
+ ASSERT(start_ < end_);
+}
+
+
+void ProfileCode::ExpandUpper(uword end) {
if (end > end_) {
end_ = end;
}
@@ -712,18 +733,26 @@ class ProfileCodeTable : public ZoneAllocated {
// Find the table index to the ProfileCode containing pc.
// Returns < 0 if not found.
intptr_t FindCodeIndexForPC(uword pc) const {
- intptr_t index = FindCodeIndex(pc, &CompareLowerBound);
- if (index == length()) {
- // Not present.
- return -1;
- }
- const ProfileCode* code = At(index);
- if (!code->Contains(pc)) {
- // Not present.
- return -1;
+ intptr_t length = table_.length();
+ if (length == 0) {
+ return -1; // No found.
zra 2017/06/14 05:00:05 Not
rmacnak 2017/06/14 17:32:14 Done.
+ }
+ intptr_t lo = 0;
+ intptr_t hi = length - 1;
+ while (lo <= hi) {
+ intptr_t mid = (hi - lo + 1) / 2 + lo;
+ ASSERT(mid >= lo);
+ ASSERT(mid <= hi);
+ ProfileCode* code = At(mid);
+ if (code->Contains(pc)) {
+ return mid;
+ } else if (pc < code->start()) {
+ hi = mid - 1;
+ } else {
+ lo = mid + 1;
+ }
}
- // Found at index.
- return index;
+ return -1;
}
ProfileCode* FindCodeForPC(uword pc) const {
@@ -737,101 +766,111 @@ class ProfileCodeTable : public ZoneAllocated {
// Insert |new_code| into the table. Returns the table index where |new_code|
// was inserted. Will merge with an overlapping ProfileCode if one is present.
intptr_t InsertCode(ProfileCode* new_code) {
- const uword start = new_code->start();
- const uword end = new_code->end();
const intptr_t length = table_.length();
if (length == 0) {
table_.Add(new_code);
return length;
}
+
// Determine the correct place to insert or merge |new_code| into table.
- intptr_t lo = FindCodeIndex(start, &CompareLowerBound);
- intptr_t hi = FindCodeIndex(end - 1, &CompareUpperBound);
- // TODO(johnmccutchan): Simplify below logic.
- if ((lo == length) && (hi == length)) {
- lo = length - 1;
- }
- if (lo == length) {
- ProfileCode* code = At(hi);
- if (code->Overlaps(new_code)) {
- HandleOverlap(code, new_code, start, end);
- return hi;
- }
- table_.Add(new_code);
- return length;
- } else if (hi == length) {
- ProfileCode* code = At(lo);
- if (code->Overlaps(new_code)) {
- HandleOverlap(code, new_code, start, end);
- return lo;
- }
- table_.Add(new_code);
- return length;
- } else if (lo == hi) {
- ProfileCode* code = At(lo);
- if (code->Overlaps(new_code)) {
- HandleOverlap(code, new_code, start, end);
- return lo;
- }
- table_.InsertAt(lo, new_code);
+ intptr_t lo = -1;
+ intptr_t hi = -1;
+ ProfileCode* lo_code = NULL;
+ ProfileCode* hi_code = NULL;
+ const uword pc = new_code->end() - 1;
+ FindNeighbors(pc, &lo, &hi, &lo_code, &hi_code);
+ ASSERT((lo_code != NULL) || (hi_code != NULL));
+
+ if (lo != -1) {
+ // Has left neighbor.
+ new_code->TruncateLower(lo_code->end());
+ ASSERT(!new_code->Overlaps(lo_code));
+ }
+ if (hi != -1) {
+ // Has right neighbor.
+ new_code->TruncateUpper(hi_code->start());
+ ASSERT(!new_code->Overlaps(hi_code));
+ }
+
+ if ((lo != -1) && (lo_code->kind() == ProfileCode::kNativeCode) &&
+ (new_code->kind() == ProfileCode::kNativeCode) &&
+ (lo_code->end() == new_code->start())) {
+ // Adjacent left neighbor of the same kind: merge.
+ // (dladdr doesn't give us symbol size so we may new PCs we didn't
zra 2017/06/14 05:00:05 may see new PCs
rmacnak 2017/06/14 17:32:14 Done.
+ // previously know belonged to it.)
+ lo_code->ExpandUpper(new_code->end());
return lo;
- } else {
- ProfileCode* code = At(lo);
- if (code->Overlaps(new_code)) {
- HandleOverlap(code, new_code, start, end);
- return lo;
- }
- code = At(hi);
- if (code->Overlaps(new_code)) {
- HandleOverlap(code, new_code, start, end);
- return hi;
- }
- table_.InsertAt(hi, new_code);
+ }
+
+ if ((hi != -1) && (hi_code->kind() == ProfileCode::kNativeCode) &&
+ (new_code->kind() == ProfileCode::kNativeCode) &&
+ (new_code->end() == hi_code->start())) {
+ // Adjacent right neighbor of the same kind: merge.
+ // (dladdr doesn't give us symbol size so we may new PCs we didn't
zra 2017/06/14 05:00:05 may see new PCs
rmacnak 2017/06/14 17:32:14 Done.
+ // previously know belonged to it.)
+ hi_code->ExpandLower(new_code->start());
return hi;
}
- UNREACHABLE();
- return -1;
+
+ intptr_t insert;
+ if (lo == -1) {
+ insert = 0;
+ } else if (hi == -1) {
+ insert = length;
+ } else {
+ insert = lo + 1;
+ }
+ table_.InsertAt(insert, new_code);
+ return insert;
}
private:
- intptr_t FindCodeIndex(uword pc, RangeCompare comparator) const {
- ASSERT(comparator != NULL);
- intptr_t count = table_.length();
- intptr_t first = 0;
- while (count > 0) {
- intptr_t it = first;
- intptr_t step = count / 2;
- it += step;
- const ProfileCode* code = At(it);
- if (comparator(pc, code->start(), code->end())) {
- first = ++it;
- count -= (step + 1);
- } else {
- count = step;
- }
+ void FindNeighbors(uword pc,
+ intptr_t* lo,
+ intptr_t* hi,
+ ProfileCode** lo_code,
+ ProfileCode** hi_code) const {
+ ASSERT(table_.length() >= 1);
+
+ intptr_t length = table_.length();
+
+ if (pc < At(0)->start()) {
+ // Lower than any existing code.
+ *lo = -1;
+ *lo_code = NULL;
+ *hi = 0;
+ *hi_code = At(*hi);
+ return;
}
- return first;
- }
- static bool CompareUpperBound(uword pc, uword start, uword end) {
- return pc >= end;
- }
+ if (pc >= At(length - 1)->end()) {
+ // Higher than any existing code.
+ *lo = length - 1;
+ *lo_code = At(*lo);
+ *hi = -1;
+ *hi_code = NULL;
+ return;
+ }
- static bool CompareLowerBound(uword pc, uword start, uword end) {
- return end <= pc;
- }
+ *lo = 0;
+ *lo_code = At(*lo);
+ *hi = length - 1;
+ *hi_code = At(*hi);
- void HandleOverlap(ProfileCode* existing,
- ProfileCode* code,
- uword start,
- uword end) {
- // We should never see overlapping Dart code regions.
- ASSERT(existing->kind() != ProfileCode::kDartCode);
- // We should never see overlapping Tag code regions.
- ASSERT(existing->kind() != ProfileCode::kTagCode);
- // When code regions overlap, they should be of the same kind.
- ASSERT(existing->kind() == code->kind());
- existing->AdjustExtent(start, end);
+ while ((*hi - *lo) > 1) {
+ intptr_t mid = (*hi - *lo + 1) / 2 + *lo;
+ ASSERT(*lo <= mid);
+ ASSERT(*hi >= mid);
+ ProfileCode* code = At(mid);
+ if (code->start() <= pc) {
+ *lo = mid;
+ *lo_code = code;
+ }
+ if (pc < code->end()) {
+ *hi = mid;
+ *hi_code = code;
+ }
+ }
}
void VerifyOrder() {
@@ -2239,6 +2278,24 @@ class ProfileBuilder : public ValueObject {
native_start &= ~1;
#endif
+ if (native_start > pc) {
+ // Bogus lookup result.
+ if (native_name != NULL) {
+ NativeSymbolResolver::FreeSymbolName(native_name);
+ native_name = NULL;
+ }
+ native_start = pc;
+ }
+ if ((pc - native_start) > (32 * KB)) {
+ // Suspect lookup result. More likely dladdr going off the rails than a
+ // jumbo function.
+ if (native_name != NULL) {
+ NativeSymbolResolver::FreeSymbolName(native_name);
+ native_name = NULL;
+ }
+ native_start = pc;
+ }
+
ASSERT(pc >= native_start);
profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start,
pc + 1, 0, code);
« no previous file with comments | « runtime/vm/profiler_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698