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

Side by Side Diff: runtime/vm/profiler_service.cc

Issue 2939853002: [fuchsia] Make profile processing resilient to bogus overlaps from dladdr. (Closed)
Patch Set: . 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 unified diff | Download patch
« no previous file with comments | « runtime/vm/profiler_service.h ('k') | runtime/vm/profiler_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/profiler_service.h" 5 #include "vm/profiler_service.h"
6 6
7 #include "vm/growable_array.h" 7 #include "vm/growable_array.h"
8 #include "vm/hash_map.h" 8 #include "vm/hash_map.h"
9 #include "vm/log.h" 9 #include "vm/log.h"
10 #include "vm/malloc_hooks.h" 10 #include "vm/malloc_hooks.h"
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 inclusive_ticks_(0), 295 inclusive_ticks_(0),
296 inclusive_serial_(-1), 296 inclusive_serial_(-1),
297 code_(code), 297 code_(code),
298 name_(NULL), 298 name_(NULL),
299 compile_timestamp_(0), 299 compile_timestamp_(0),
300 function_(NULL), 300 function_(NULL),
301 code_table_index_(-1), 301 code_table_index_(-1),
302 address_ticks_(0) {} 302 address_ticks_(0) {}
303 303
304 304
305 void ProfileCode::AdjustExtent(uword start, uword end) { 305 void ProfileCode::TruncateLower(uword start) {
306 if (start > start_) {
307 start_ = start;
308 }
309 ASSERT(start_ < end_);
310 }
311
312
313 void ProfileCode::TruncateUpper(uword end) {
314 if (end < end_) {
315 end_ = end;
316 }
317 ASSERT(start_ < end_);
318 }
319
320
321 void ProfileCode::ExpandLower(uword start) {
306 if (start < start_) { 322 if (start < start_) {
307 start_ = start; 323 start_ = start;
308 } 324 }
325 ASSERT(start_ < end_);
326 }
327
328
329 void ProfileCode::ExpandUpper(uword end) {
309 if (end > end_) { 330 if (end > end_) {
310 end_ = end; 331 end_ = end;
311 } 332 }
312 ASSERT(start_ < end_); 333 ASSERT(start_ < end_);
313 } 334 }
314 335
315 336
316 bool ProfileCode::Overlaps(const ProfileCode* other) const { 337 bool ProfileCode::Overlaps(const ProfileCode* other) const {
317 ASSERT(other != NULL); 338 ASSERT(other != NULL);
318 return other->Contains(start_) || other->Contains(end_ - 1) || 339 return other->Contains(start_) || other->Contains(end_ - 1) ||
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 } 709 }
689 ASSERT(function != NULL); 710 ASSERT(function != NULL);
690 711
691 function->AddProfileCode(code_table_index()); 712 function->AddProfileCode(code_table_index());
692 713
693 function_ = function; 714 function_ = function;
694 return function_; 715 return function_;
695 } 716 }
696 717
697 718
698 typedef bool (*RangeCompare)(uword pc, uword region_start, uword region_end); 719 intptr_t ProfileCodeTable::FindCodeIndexForPC(uword pc) const {
720 intptr_t length = table_.length();
721 if (length == 0) {
722 return -1; // Not found.
723 }
724 intptr_t lo = 0;
725 intptr_t hi = length - 1;
726 while (lo <= hi) {
727 intptr_t mid = (hi - lo + 1) / 2 + lo;
728 ASSERT(mid >= lo);
729 ASSERT(mid <= hi);
730 ProfileCode* code = At(mid);
731 if (code->Contains(pc)) {
732 return mid;
733 } else if (pc < code->start()) {
734 hi = mid - 1;
735 } else {
736 lo = mid + 1;
737 }
738 }
739 return -1;
740 }
699 741
700 class ProfileCodeTable : public ZoneAllocated {
701 public:
702 ProfileCodeTable() : table_(8) {}
703 742
704 intptr_t length() const { return table_.length(); } 743 intptr_t ProfileCodeTable::InsertCode(ProfileCode* new_code) {
705 744 const intptr_t length = table_.length();
706 ProfileCode* At(intptr_t index) const { 745 if (length == 0) {
707 ASSERT(index >= 0); 746 table_.Add(new_code);
708 ASSERT(index < length()); 747 return length;
709 return table_[index];
710 } 748 }
711 749
712 // Find the table index to the ProfileCode containing pc. 750 // Determine the correct place to insert or merge |new_code| into table.
713 // Returns < 0 if not found. 751 intptr_t lo = -1;
714 intptr_t FindCodeIndexForPC(uword pc) const { 752 intptr_t hi = -1;
715 intptr_t index = FindCodeIndex(pc, &CompareLowerBound); 753 ProfileCode* lo_code = NULL;
716 if (index == length()) { 754 ProfileCode* hi_code = NULL;
717 // Not present. 755 const uword pc = new_code->end() - 1;
718 return -1; 756 FindNeighbors(pc, &lo, &hi, &lo_code, &hi_code);
719 } 757 ASSERT((lo_code != NULL) || (hi_code != NULL));
720 const ProfileCode* code = At(index); 758
721 if (!code->Contains(pc)) { 759 if (lo != -1) {
722 // Not present. 760 // Has left neighbor.
723 return -1; 761 new_code->TruncateLower(lo_code->end());
724 } 762 ASSERT(!new_code->Overlaps(lo_code));
725 // Found at index. 763 }
726 return index; 764 if (hi != -1) {
765 // Has right neighbor.
766 new_code->TruncateUpper(hi_code->start());
767 ASSERT(!new_code->Overlaps(hi_code));
727 } 768 }
728 769
729 ProfileCode* FindCodeForPC(uword pc) const { 770 if ((lo != -1) && (lo_code->kind() == ProfileCode::kNativeCode) &&
730 intptr_t index = FindCodeIndexForPC(pc); 771 (new_code->kind() == ProfileCode::kNativeCode) &&
731 if (index < 0) { 772 (lo_code->end() == new_code->start())) {
732 return NULL; 773 // Adjacent left neighbor of the same kind: merge.
733 } 774 // (dladdr doesn't give us symbol size so processing more samples may see
734 return At(index); 775 // more PCs we didn't previously know belonged to it.)
776 lo_code->ExpandUpper(new_code->end());
777 return lo;
735 } 778 }
736 779
737 // Insert |new_code| into the table. Returns the table index where |new_code| 780 if ((hi != -1) && (hi_code->kind() == ProfileCode::kNativeCode) &&
738 // was inserted. Will merge with an overlapping ProfileCode if one is present. 781 (new_code->kind() == ProfileCode::kNativeCode) &&
739 intptr_t InsertCode(ProfileCode* new_code) { 782 (new_code->end() == hi_code->start())) {
740 const uword start = new_code->start(); 783 // Adjacent right neighbor of the same kind: merge.
741 const uword end = new_code->end(); 784 // (dladdr doesn't give us symbol size so processing more samples may see
742 const intptr_t length = table_.length(); 785 // more PCs we didn't previously know belonged to it.)
743 if (length == 0) { 786 hi_code->ExpandLower(new_code->start());
744 table_.Add(new_code); 787 return hi;
745 return length;
746 }
747 // Determine the correct place to insert or merge |new_code| into table.
748 intptr_t lo = FindCodeIndex(start, &CompareLowerBound);
749 intptr_t hi = FindCodeIndex(end - 1, &CompareUpperBound);
750 // TODO(johnmccutchan): Simplify below logic.
751 if ((lo == length) && (hi == length)) {
752 lo = length - 1;
753 }
754 if (lo == length) {
755 ProfileCode* code = At(hi);
756 if (code->Overlaps(new_code)) {
757 HandleOverlap(code, new_code, start, end);
758 return hi;
759 }
760 table_.Add(new_code);
761 return length;
762 } else if (hi == length) {
763 ProfileCode* code = At(lo);
764 if (code->Overlaps(new_code)) {
765 HandleOverlap(code, new_code, start, end);
766 return lo;
767 }
768 table_.Add(new_code);
769 return length;
770 } else if (lo == hi) {
771 ProfileCode* code = At(lo);
772 if (code->Overlaps(new_code)) {
773 HandleOverlap(code, new_code, start, end);
774 return lo;
775 }
776 table_.InsertAt(lo, new_code);
777 return lo;
778 } else {
779 ProfileCode* code = At(lo);
780 if (code->Overlaps(new_code)) {
781 HandleOverlap(code, new_code, start, end);
782 return lo;
783 }
784 code = At(hi);
785 if (code->Overlaps(new_code)) {
786 HandleOverlap(code, new_code, start, end);
787 return hi;
788 }
789 table_.InsertAt(hi, new_code);
790 return hi;
791 }
792 UNREACHABLE();
793 return -1;
794 } 788 }
795 789
796 private: 790 intptr_t insert;
797 intptr_t FindCodeIndex(uword pc, RangeCompare comparator) const { 791 if (lo == -1) {
798 ASSERT(comparator != NULL); 792 insert = 0;
799 intptr_t count = table_.length(); 793 } else if (hi == -1) {
800 intptr_t first = 0; 794 insert = length;
801 while (count > 0) { 795 } else {
802 intptr_t it = first; 796 insert = lo + 1;
803 intptr_t step = count / 2; 797 }
804 it += step; 798 table_.InsertAt(insert, new_code);
805 const ProfileCode* code = At(it); 799 return insert;
806 if (comparator(pc, code->start(), code->end())) { 800 }
807 first = ++it; 801
808 count -= (step + 1); 802
809 } else { 803 void ProfileCodeTable::FindNeighbors(uword pc,
810 count = step; 804 intptr_t* lo,
811 } 805 intptr_t* hi,
812 } 806 ProfileCode** lo_code,
813 return first; 807 ProfileCode** hi_code) const {
808 ASSERT(table_.length() >= 1);
809
810 intptr_t length = table_.length();
811
812 if (pc < At(0)->start()) {
813 // Lower than any existing code.
814 *lo = -1;
815 *lo_code = NULL;
816 *hi = 0;
817 *hi_code = At(*hi);
818 return;
814 } 819 }
815 820
816 static bool CompareUpperBound(uword pc, uword start, uword end) { 821 if (pc >= At(length - 1)->end()) {
817 return pc >= end; 822 // Higher than any existing code.
823 *lo = length - 1;
824 *lo_code = At(*lo);
825 *hi = -1;
826 *hi_code = NULL;
827 return;
818 } 828 }
819 829
820 static bool CompareLowerBound(uword pc, uword start, uword end) { 830 *lo = 0;
821 return end <= pc; 831 *lo_code = At(*lo);
822 } 832 *hi = length - 1;
833 *hi_code = At(*hi);
823 834
824 void HandleOverlap(ProfileCode* existing, 835 while ((*hi - *lo) > 1) {
825 ProfileCode* code, 836 intptr_t mid = (*hi - *lo + 1) / 2 + *lo;
826 uword start, 837 ASSERT(*lo <= mid);
827 uword end) { 838 ASSERT(*hi >= mid);
828 // We should never see overlapping Dart code regions. 839 ProfileCode* code = At(mid);
829 ASSERT(existing->kind() != ProfileCode::kDartCode); 840 if (code->end() <= pc) {
830 // We should never see overlapping Tag code regions. 841 *lo = mid;
831 ASSERT(existing->kind() != ProfileCode::kTagCode); 842 *lo_code = code;
832 // When code regions overlap, they should be of the same kind.
833 ASSERT(existing->kind() == code->kind());
834 existing->AdjustExtent(start, end);
835 }
836
837 void VerifyOrder() {
838 const intptr_t length = table_.length();
839 if (length == 0) {
840 return;
841 } 843 }
842 uword last = table_[0]->end(); 844 if (pc < code->end()) {
843 for (intptr_t i = 1; i < length; i++) { 845 *hi = mid;
844 ProfileCode* a = table_[i]; 846 *hi_code = code;
845 ASSERT(last <= a->start());
846 last = a->end();
847 } 847 }
848 } 848 }
849 }
849 850
850 void VerifyOverlap() { 851
851 const intptr_t length = table_.length(); 852 void ProfileCodeTable::VerifyOrder() {
852 for (intptr_t i = 0; i < length; i++) { 853 const intptr_t length = table_.length();
853 ProfileCode* a = table_[i]; 854 if (length == 0) {
854 for (intptr_t j = i + 1; j < length; j++) { 855 return;
855 ProfileCode* b = table_[j]; 856 }
856 ASSERT(!a->Contains(b->start()) && !a->Contains(b->end() - 1) && 857 uword last = table_[0]->end();
857 !b->Contains(a->start()) && !b->Contains(a->end() - 1)); 858 for (intptr_t i = 1; i < length; i++) {
858 } 859 ProfileCode* a = table_[i];
860 ASSERT(last <= a->start());
861 last = a->end();
862 }
863 }
864
865 void ProfileCodeTable::VerifyOverlap() {
866 const intptr_t length = table_.length();
867 for (intptr_t i = 0; i < length; i++) {
868 ProfileCode* a = table_[i];
869 for (intptr_t j = i + 1; j < length; j++) {
870 ProfileCode* b = table_[j];
871 ASSERT(!a->Contains(b->start()) && !a->Contains(b->end() - 1) &&
872 !b->Contains(a->start()) && !b->Contains(a->end() - 1));
859 } 873 }
860 } 874 }
861 875 }
862 ZoneGrowableArray<ProfileCode*> table_;
863 };
864 876
865 877
866 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) 878 ProfileTrieNode::ProfileTrieNode(intptr_t table_index)
867 : table_index_(table_index), 879 : table_index_(table_index),
868 count_(0), 880 count_(0),
869 exclusive_allocations_(0), 881 exclusive_allocations_(0),
870 inclusive_allocations_(0), 882 inclusive_allocations_(0),
871 children_(0), 883 children_(0),
872 frame_id_(-1) { 884 frame_id_(-1) {
873 ASSERT(table_index_ >= 0); 885 ASSERT(table_index_ >= 0);
(...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after
2232 // Failed to find a native symbol for pc. 2244 // Failed to find a native symbol for pc.
2233 native_start = pc; 2245 native_start = pc;
2234 } 2246 }
2235 2247
2236 #if defined(HOST_ARCH_ARM) 2248 #if defined(HOST_ARCH_ARM)
2237 // The symbol for a Thumb function will be xxx1, but we may have samples 2249 // The symbol for a Thumb function will be xxx1, but we may have samples
2238 // at function entry which will have pc xxx0. 2250 // at function entry which will have pc xxx0.
2239 native_start &= ~1; 2251 native_start &= ~1;
2240 #endif 2252 #endif
2241 2253
2254 if (native_start > pc) {
2255 // Bogus lookup result.
2256 if (native_name != NULL) {
2257 NativeSymbolResolver::FreeSymbolName(native_name);
2258 native_name = NULL;
2259 }
2260 native_start = pc;
2261 }
2262 if ((pc - native_start) > (32 * KB)) {
2263 // Suspect lookup result. More likely dladdr going off the rails than a
2264 // jumbo function.
2265 if (native_name != NULL) {
2266 NativeSymbolResolver::FreeSymbolName(native_name);
2267 native_name = NULL;
2268 }
2269 native_start = pc;
2270 }
2271
2242 ASSERT(pc >= native_start); 2272 ASSERT(pc >= native_start);
2243 profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start, 2273 profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start,
2244 pc + 1, 0, code); 2274 pc + 1, 0, code);
2245 if (native_name != NULL) { 2275 if (native_name != NULL) {
2246 profile_code->SetName(native_name); 2276 profile_code->SetName(native_name);
2247 NativeSymbolResolver::FreeSymbolName(native_name); 2277 NativeSymbolResolver::FreeSymbolName(native_name);
2248 } 2278 }
2249 2279
2250 RegisterLiveProfileCode(profile_code); 2280 RegisterLiveProfileCode(profile_code);
2251 return profile_code; 2281 return profile_code;
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
2848 // Disable thread interrupts while processing the buffer. 2878 // Disable thread interrupts while processing the buffer.
2849 DisableThreadInterruptsScope dtis(thread); 2879 DisableThreadInterruptsScope dtis(thread);
2850 2880
2851 ClearProfileVisitor clear_profile(isolate); 2881 ClearProfileVisitor clear_profile(isolate);
2852 sample_buffer->VisitSamples(&clear_profile); 2882 sample_buffer->VisitSamples(&clear_profile);
2853 } 2883 }
2854 2884
2855 #endif // !PRODUCT 2885 #endif // !PRODUCT
2856 2886
2857 } // namespace dart 2887 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler_service.h ('k') | runtime/vm/profiler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698