OLD | NEW |
1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 // Determine the distribution of bytes in the shadow. | 651 // Determine the distribution of bytes in the shadow. |
652 size_t left_redzone_bytes = info.TotalHeaderSize() / kShadowRatio; | 652 size_t left_redzone_bytes = info.TotalHeaderSize() / kShadowRatio; |
653 size_t body_bytes = (info.body_size + kShadowRatio - 1) / kShadowRatio; | 653 size_t body_bytes = (info.body_size + kShadowRatio - 1) / kShadowRatio; |
654 size_t block_bytes = info.block_size / kShadowRatio; | 654 size_t block_bytes = info.block_size / kShadowRatio; |
655 size_t right_redzone_bytes = block_bytes - left_redzone_bytes - body_bytes; | 655 size_t right_redzone_bytes = block_bytes - left_redzone_bytes - body_bytes; |
656 | 656 |
657 // Determine the marker byte for the header. This encodes the length of the | 657 // Determine the marker byte for the header. This encodes the length of the |
658 // body of the allocation modulo the shadow ratio, so that the exact length | 658 // body of the allocation modulo the shadow ratio, so that the exact length |
659 // can be inferred from inspecting the shadow memory. | 659 // can be inferred from inspecting the shadow memory. |
660 uint8_t body_size_mod = info.body_size % kShadowRatio; | 660 uint8_t body_size_mod = info.body_size % kShadowRatio; |
661 ShadowMarker header_marker = ShadowMarkerHelper::BuildBlockStart( | 661 ShadowMarker header_marker = |
662 true, info.header->is_nested, body_size_mod); | 662 ShadowMarkerHelper::BuildBlockStart(true, body_size_mod); |
663 | 663 |
664 // Determine the marker byte for the trailer. | 664 // Determine the marker byte for the trailer. |
665 ShadowMarker trailer_marker = | 665 ShadowMarker trailer_marker = ShadowMarkerHelper::BuildBlockEnd(true); |
666 ShadowMarkerHelper::BuildBlockEnd(true, info.header->is_nested); | |
667 | 666 |
668 // Poison the header and left padding. | 667 // Poison the header and left padding. |
669 uint8_t* cursor = shadow_ + index; | 668 uint8_t* cursor = shadow_ + index; |
670 ::memset(cursor, header_marker, 1); | 669 ::memset(cursor, header_marker, 1); |
671 ::memset(cursor + 1, kHeapLeftPaddingMarker, left_redzone_bytes - 1); | 670 ::memset(cursor + 1, kHeapLeftPaddingMarker, left_redzone_bytes - 1); |
672 cursor += left_redzone_bytes; | 671 cursor += left_redzone_bytes; |
673 ::memset(cursor, kHeapAddressableMarker, body_bytes); | 672 ::memset(cursor, kHeapAddressableMarker, body_bytes); |
674 cursor += body_bytes; | 673 cursor += body_bytes; |
675 | 674 |
676 // Poison the right padding and the trailer. | 675 // Poison the right padding and the trailer. |
677 if (body_size_mod > 0) | 676 if (body_size_mod > 0) |
678 cursor[-1] = body_size_mod; | 677 cursor[-1] = body_size_mod; |
679 ::memset(cursor, kHeapRightPaddingMarker, right_redzone_bytes - 1); | 678 ::memset(cursor, kHeapRightPaddingMarker, right_redzone_bytes - 1); |
680 ::memset(cursor + right_redzone_bytes - 1, trailer_marker, 1); | 679 ::memset(cursor + right_redzone_bytes - 1, trailer_marker, 1); |
681 | 680 |
682 SetShadowMemory(info.header, | 681 SetShadowMemory(info.header, |
683 info.TotalHeaderSize(), | 682 info.TotalHeaderSize(), |
684 kHeapLeftPaddingMarker); | 683 kHeapLeftPaddingMarker); |
685 SetShadowMemory(info.body, info.body_size, kHeapAddressableMarker); | 684 SetShadowMemory(info.body, info.body_size, kHeapAddressableMarker); |
686 SetShadowMemory(info.trailer_padding, | 685 SetShadowMemory(info.trailer_padding, |
687 info.TotalTrailerSize(), | 686 info.TotalTrailerSize(), |
688 kHeapRightPaddingMarker); | 687 kHeapRightPaddingMarker); |
689 } | 688 } |
690 | 689 |
691 bool Shadow::BlockIsNested(const BlockInfo& info) const { | |
692 uint8_t marker = GetShadowMarkerForAddress(info.header); | |
693 DCHECK(ShadowMarkerHelper::IsActiveBlockStart(marker)); | |
694 return ShadowMarkerHelper::IsNestedBlockStart(marker); | |
695 } | |
696 | |
697 bool Shadow::BlockInfoFromShadow( | 690 bool Shadow::BlockInfoFromShadow( |
698 const void* addr, CompactBlockInfo* info) const { | 691 const void* addr, CompactBlockInfo* info) const { |
699 DCHECK_NE(static_cast<void*>(NULL), addr); | 692 DCHECK_NE(static_cast<void*>(NULL), addr); |
700 DCHECK_NE(static_cast<CompactBlockInfo*>(NULL), info); | 693 DCHECK_NE(static_cast<CompactBlockInfo*>(NULL), info); |
701 if (!BlockInfoFromShadowImpl(0, addr, info)) | 694 if (!BlockInfoFromShadowImpl(addr, info)) |
702 return false; | 695 return false; |
703 return true; | 696 return true; |
704 } | 697 } |
705 | 698 |
706 bool Shadow::BlockInfoFromShadow(const void* addr, BlockInfo* info) const { | 699 bool Shadow::BlockInfoFromShadow(const void* addr, BlockInfo* info) const { |
707 DCHECK_NE(static_cast<void*>(NULL), addr); | 700 DCHECK_NE(static_cast<void*>(NULL), addr); |
708 DCHECK_NE(static_cast<BlockInfo*>(NULL), info); | 701 DCHECK_NE(static_cast<BlockInfo*>(NULL), info); |
709 CompactBlockInfo compact = {}; | 702 CompactBlockInfo compact = {}; |
710 if (!BlockInfoFromShadow(addr, &compact)) | 703 if (!BlockInfoFromShadow(addr, &compact)) |
711 return false; | 704 return false; |
712 ConvertBlockInfo(compact, info); | 705 ConvertBlockInfo(compact, info); |
713 return true; | 706 return true; |
714 } | 707 } |
715 | 708 |
716 bool Shadow::ParentBlockInfoFromShadow(const BlockInfo& nested, | |
717 BlockInfo* info) const { | |
718 DCHECK_NE(static_cast<BlockInfo*>(NULL), info); | |
719 if (!BlockIsNested(nested)) | |
720 return false; | |
721 CompactBlockInfo compact = {}; | |
722 if (!BlockInfoFromShadowImpl(1, nested.header, &compact)) | |
723 return false; | |
724 ConvertBlockInfo(compact, info); | |
725 return true; | |
726 } | |
727 | |
728 bool Shadow::IsBeginningOfBlockBody(const void* addr) const { | 709 bool Shadow::IsBeginningOfBlockBody(const void* addr) const { |
729 DCHECK_NE(static_cast<void*>(NULL), addr); | 710 DCHECK_NE(static_cast<void*>(NULL), addr); |
730 // If the block has a non-zero body size then the beginning of the body will | 711 // If the block has a non-zero body size then the beginning of the body will |
731 // be accessible or tagged as freed. | 712 // be accessible or tagged as freed. |
732 // If the block has an empty body then the beginning of the body will be a | 713 // If the block has an empty body then the beginning of the body will be a |
733 // right redzone. | 714 // right redzone. |
734 if (IsAccessible(addr) || IsRightRedzone(addr) || | 715 if (IsAccessible(addr) || IsRightRedzone(addr) || |
735 GetShadowMarkerForAddress(addr) == kHeapFreedMarker) { | 716 GetShadowMarkerForAddress(addr) == kHeapFreedMarker) { |
736 return IsLeftRedzone(reinterpret_cast<const uint8_t*>(addr) - 1); | 717 return IsLeftRedzone(reinterpret_cast<const uint8_t*>(addr) - 1); |
737 } | 718 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 void Shadow::AppendShadowMemoryText( | 821 void Shadow::AppendShadowMemoryText( |
841 const void* addr, std::string* output) const { | 822 const void* addr, std::string* output) const { |
842 base::StringAppendF(output, "Shadow bytes around the buggy address:\n"); | 823 base::StringAppendF(output, "Shadow bytes around the buggy address:\n"); |
843 AppendShadowArrayText(addr, output); | 824 AppendShadowArrayText(addr, output); |
844 base::StringAppendF(output, "Shadow byte legend (one shadow byte represents " | 825 base::StringAppendF(output, "Shadow byte legend (one shadow byte represents " |
845 "8 application bytes):\n"); | 826 "8 application bytes):\n"); |
846 base::StringAppendF(output, " Addressable: 00\n"); | 827 base::StringAppendF(output, " Addressable: 00\n"); |
847 base::StringAppendF(output, " Partially addressable: 01 - 07\n"); | 828 base::StringAppendF(output, " Partially addressable: 01 - 07\n"); |
848 base::StringAppendF(output, " Block start redzone: %02x - %02x\n", | 829 base::StringAppendF(output, " Block start redzone: %02x - %02x\n", |
849 kHeapBlockStartMarker0, kHeapBlockStartMarker7); | 830 kHeapBlockStartMarker0, kHeapBlockStartMarker7); |
850 base::StringAppendF(output, " Nested block start: %02x - %02x\n", | |
851 kHeapNestedBlockStartMarker0, | |
852 kHeapNestedBlockStartMarker7); | |
853 base::StringAppendF(output, " Asan memory byte: %02x\n", | 831 base::StringAppendF(output, " Asan memory byte: %02x\n", |
854 kAsanMemoryMarker); | 832 kAsanMemoryMarker); |
855 base::StringAppendF(output, " Invalid address: %02x\n", | 833 base::StringAppendF(output, " Invalid address: %02x\n", |
856 kInvalidAddressMarker); | 834 kInvalidAddressMarker); |
857 base::StringAppendF(output, " User redzone: %02x\n", | 835 base::StringAppendF(output, " User redzone: %02x\n", |
858 kUserRedzoneMarker); | 836 kUserRedzoneMarker); |
859 base::StringAppendF(output, " Block end redzone: %02x\n", | 837 base::StringAppendF(output, " Block end redzone: %02x\n", |
860 kHeapBlockEndMarker); | 838 kHeapBlockEndMarker); |
861 base::StringAppendF(output, " Nested block end: %02x\n", | |
862 kHeapNestedBlockEndMarker); | |
863 base::StringAppendF(output, " Heap left redzone: %02x\n", | 839 base::StringAppendF(output, " Heap left redzone: %02x\n", |
864 kHeapLeftPaddingMarker); | 840 kHeapLeftPaddingMarker); |
865 base::StringAppendF(output, " Heap right redzone: %02x\n", | 841 base::StringAppendF(output, " Heap right redzone: %02x\n", |
866 kHeapRightPaddingMarker); | 842 kHeapRightPaddingMarker); |
867 base::StringAppendF(output, " Asan reserved byte: %02x\n", | 843 base::StringAppendF(output, " Asan reserved byte: %02x\n", |
868 kAsanReservedMarker); | 844 kAsanReservedMarker); |
869 base::StringAppendF(output, " Freed heap region: %02x\n", | 845 base::StringAppendF(output, " Freed heap region: %02x\n", |
870 kHeapFreedMarker); | 846 kHeapFreedMarker); |
871 } | 847 } |
872 | 848 |
873 size_t Shadow::GetAllocSize(const uint8_t* mem) const { | 849 size_t Shadow::GetAllocSize(const uint8_t* mem) const { |
874 BlockInfo block_info = {}; | 850 BlockInfo block_info = {}; |
875 if (!Shadow::BlockInfoFromShadow(mem, &block_info)) | 851 if (!Shadow::BlockInfoFromShadow(mem, &block_info)) |
876 return 0; | 852 return 0; |
877 return block_info.block_size; | 853 return block_info.block_size; |
878 } | 854 } |
879 | 855 |
880 bool Shadow::ScanLeftForBracketingBlockStart( | 856 bool Shadow::ScanLeftForBracketingBlockStart(size_t cursor, |
881 size_t initial_nesting_depth, size_t cursor, size_t* location) const { | 857 size_t* location) const { |
882 DCHECK_NE(static_cast<size_t*>(NULL), location); | 858 DCHECK_NE(static_cast<size_t*>(NULL), location); |
883 | 859 |
884 static const size_t kLowerBound = kAddressLowerBound / kShadowRatio; | 860 static const size_t kLowerBound = kAddressLowerBound / kShadowRatio; |
885 | 861 |
886 size_t left = cursor; | 862 size_t left = cursor; |
887 int nesting_depth = static_cast<int>(initial_nesting_depth); | |
888 | 863 |
889 MEMORY_BASIC_INFORMATION memory_info = {}; | 864 MEMORY_BASIC_INFORMATION memory_info = {}; |
890 SIZE_T ret = | 865 SIZE_T ret = |
891 ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info)); | 866 ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info)); |
892 DCHECK_GT(ret, 0u); | 867 DCHECK_GT(ret, 0u); |
893 if (memory_info.State != MEM_COMMIT) | 868 if (memory_info.State != MEM_COMMIT) |
894 return false; | 869 return false; |
895 | 870 |
896 if (ShadowMarkerHelper::IsBlockEnd(shadow_[left])) | |
897 --nesting_depth; | |
898 while (true) { | 871 while (true) { |
899 if (&shadow_[left] < static_cast<const uint8_t*>(memory_info.BaseAddress)) { | 872 if (&shadow_[left] < static_cast<const uint8_t*>(memory_info.BaseAddress)) { |
900 ret = ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info)); | 873 ret = ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info)); |
901 DCHECK_GT(ret, 0u); | 874 DCHECK_GT(ret, 0u); |
902 if (memory_info.State != MEM_COMMIT) | 875 if (memory_info.State != MEM_COMMIT) |
903 return false; | 876 return false; |
904 } | 877 } |
905 if (ShadowMarkerHelper::IsBlockStart(shadow_[left])) { | 878 if (ShadowMarkerHelper::IsBlockStart(shadow_[left])) { |
906 if (nesting_depth == 0) { | 879 *location = left; |
907 *location = left; | 880 return true; |
908 return true; | |
909 } | |
910 // If this is not a nested block then there's no hope of finding a | |
911 // block containing the original cursor. | |
912 if (!ShadowMarkerHelper::IsNestedBlockStart(shadow_[left])) | |
913 return false; | |
914 --nesting_depth; | |
915 } else if (ShadowMarkerHelper::IsBlockEnd(shadow_[left])) { | |
916 ++nesting_depth; | |
917 | |
918 // If we encounter the end of a non-nested block there's no way for | |
919 // a block to bracket us. | |
920 if (nesting_depth > 0 && | |
921 !ShadowMarkerHelper::IsNestedBlockEnd(shadow_[left])) { | |
922 return false; | |
923 } | |
924 } | 881 } |
925 if (left <= kLowerBound) | 882 if (left <= kLowerBound) |
926 return false; | 883 return false; |
927 --left; | 884 --left; |
928 } | 885 } |
929 | 886 |
930 NOTREACHED(); | 887 NOTREACHED(); |
931 } | 888 } |
932 | 889 |
933 namespace { | 890 namespace { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 return pos; | 961 return pos; |
1005 } | 962 } |
1006 pos += 8; | 963 pos += 8; |
1007 } | 964 } |
1008 | 965 |
1009 return pos; | 966 return pos; |
1010 } | 967 } |
1011 | 968 |
1012 } // namespace | 969 } // namespace |
1013 | 970 |
1014 bool Shadow::ScanRightForBracketingBlockEnd( | 971 bool Shadow::ScanRightForBracketingBlockEnd(size_t cursor, |
1015 size_t initial_nesting_depth, size_t cursor, size_t* location) const { | 972 size_t* location) const { |
1016 DCHECK_NE(static_cast<size_t*>(NULL), location); | 973 DCHECK_NE(static_cast<size_t*>(NULL), location); |
1017 | 974 |
1018 const uint8_t* shadow_end = shadow_ + length_; | 975 const uint8_t* shadow_end = shadow_ + length_; |
1019 const uint8_t* pos = shadow_ + cursor; | 976 const uint8_t* pos = shadow_ + cursor; |
1020 int nesting_depth = static_cast<int>(initial_nesting_depth); | |
1021 if (ShadowMarkerHelper::IsBlockStart(*pos)) | |
1022 --nesting_depth; | |
1023 while (pos < shadow_end) { | 977 while (pos < shadow_end) { |
1024 // Skips past as many addressable and freed bytes as possible. | 978 // Skips past as many addressable and freed bytes as possible. |
1025 pos = ScanRightForPotentialHeaderBytes(pos, shadow_end); | 979 pos = ScanRightForPotentialHeaderBytes(pos, shadow_end); |
1026 if (pos == shadow_end) | 980 if (pos == shadow_end) |
1027 return false; | 981 return false; |
1028 | 982 |
1029 // When the above loop exits early then somewhere in the next 8 bytes | 983 // When the above loop exits early then somewhere in the next 8 bytes |
1030 // there's non-addressable data that isn't 'freed'. Look byte by byte to | 984 // there's non-addressable data that isn't 'freed'. Look byte by byte to |
1031 // see what's up. | 985 // see what's up. |
1032 | 986 |
1033 if (ShadowMarkerHelper::IsBlockEnd(*pos)) { | 987 if (ShadowMarkerHelper::IsBlockEnd(*pos)) { |
1034 if (nesting_depth == 0) { | 988 *location = pos - shadow_; |
1035 *location = pos - shadow_; | 989 return true; |
1036 return true; | |
1037 } | |
1038 if (!ShadowMarkerHelper::IsNestedBlockEnd(*pos)) | |
1039 return false; | |
1040 --nesting_depth; | |
1041 } else if (ShadowMarkerHelper::IsBlockStart(*pos)) { | |
1042 ++nesting_depth; | |
1043 | |
1044 // If we encounter the beginning of a non-nested block then there's | |
1045 // clearly no way for any block to bracket us. | |
1046 if (nesting_depth > 0 && | |
1047 !ShadowMarkerHelper::IsNestedBlockStart(*pos)) { | |
1048 return false; | |
1049 } | |
1050 } | 990 } |
1051 ++pos; | 991 ++pos; |
1052 } | 992 } |
1053 return false; | 993 return false; |
1054 } | 994 } |
1055 | 995 |
1056 bool Shadow::BlockInfoFromShadowImpl( | 996 bool Shadow::BlockInfoFromShadowImpl( |
1057 size_t initial_nesting_depth, | |
1058 const void* addr, | 997 const void* addr, |
1059 CompactBlockInfo* info) const { | 998 CompactBlockInfo* info) const { |
1060 DCHECK_NE(static_cast<void*>(NULL), addr); | 999 DCHECK_NE(static_cast<void*>(NULL), addr); |
1061 DCHECK_NE(static_cast<CompactBlockInfo*>(NULL), info); | 1000 DCHECK_NE(static_cast<CompactBlockInfo*>(NULL), info); |
1062 | 1001 |
1063 // Convert the address to an offset in the shadow memory. | 1002 // Convert the address to an offset in the shadow memory. |
1064 size_t left = reinterpret_cast<uintptr_t>(addr) / kShadowRatio; | 1003 size_t left = reinterpret_cast<uintptr_t>(addr) / kShadowRatio; |
1065 size_t right = left; | 1004 size_t right = left; |
1066 | 1005 |
1067 if (!ScanLeftForBracketingBlockStart(initial_nesting_depth, left, &left)) | 1006 if (!ScanLeftForBracketingBlockStart(left, &left)) |
1068 return false; | 1007 return false; |
1069 if (!ScanRightForBracketingBlockEnd(initial_nesting_depth, right, &right)) | 1008 if (!ScanRightForBracketingBlockEnd(right, &right)) |
1070 return false; | 1009 return false; |
1071 ++right; | 1010 ++right; |
1072 | 1011 |
1073 uint8_t* block = reinterpret_cast<uint8_t*>(left * kShadowRatio); | 1012 uint8_t* block = reinterpret_cast<uint8_t*>(left * kShadowRatio); |
1074 info->header = reinterpret_cast<BlockHeader*>(block); | 1013 info->header = reinterpret_cast<BlockHeader*>(block); |
1075 info->block_size = static_cast<uint32_t>((right - left) * kShadowRatio); | 1014 info->block_size = static_cast<uint32_t>((right - left) * kShadowRatio); |
1076 | 1015 |
1077 // Get the length of the body modulo the shadow ratio. | 1016 // Get the length of the body modulo the shadow ratio. |
1078 size_t body_size_mod = ShadowMarkerHelper::GetBlockStartData(shadow_[left]); | 1017 size_t body_size_mod = ShadowMarkerHelper::GetBlockStartData(shadow_[left]); |
1079 info->is_nested = ShadowMarkerHelper::IsNestedBlockStart(shadow_[left]); | |
1080 | 1018 |
1081 // Find the beginning of the body (end of the left redzone). | 1019 // Find the beginning of the body (end of the left redzone). |
1082 ++left; | 1020 ++left; |
1083 while (left < right && shadow_[left] == kHeapLeftPaddingMarker) | 1021 while (left < right && shadow_[left] == kHeapLeftPaddingMarker) |
1084 ++left; | 1022 ++left; |
1085 | 1023 |
1086 // Find the beginning of the right redzone (end of the body). | 1024 // Find the beginning of the right redzone (end of the body). |
1087 --right; | 1025 --right; |
1088 while (right > left && shadow_[right - 1] == kHeapRightPaddingMarker) | 1026 while (right > left && shadow_[right - 1] == kHeapRightPaddingMarker) |
1089 --right; | 1027 --right; |
1090 | 1028 |
1091 // Calculate the body location and size. | 1029 // Calculate the body location and size. |
1092 uint8_t* body = reinterpret_cast<uint8_t*>(left * kShadowRatio); | 1030 uint8_t* body = reinterpret_cast<uint8_t*>(left * kShadowRatio); |
1093 size_t body_size = (right - left) * kShadowRatio; | 1031 size_t body_size = (right - left) * kShadowRatio; |
1094 if (body_size_mod > 0) { | 1032 if (body_size_mod > 0) { |
1095 DCHECK_LE(8u, body_size); | 1033 DCHECK_LE(8u, body_size); |
1096 body_size = body_size - kShadowRatio + body_size_mod; | 1034 body_size = body_size - kShadowRatio + body_size_mod; |
1097 } | 1035 } |
1098 | 1036 |
1099 // Fill out header and trailer sizes. | 1037 // Fill out header and trailer sizes. |
1100 info->header_size = body - block; | 1038 info->header_size = body - block; |
1101 info->trailer_size = info->block_size - body_size - info->header_size; | 1039 info->trailer_size = info->block_size - body_size - info->header_size; |
1102 | 1040 |
1103 return true; | 1041 return true; |
1104 } | 1042 } |
1105 | 1043 |
1106 ShadowWalker::ShadowWalker(const Shadow* shadow, | 1044 ShadowWalker::ShadowWalker(const Shadow* shadow, |
1107 bool recursive, | |
1108 const void* lower_bound, | 1045 const void* lower_bound, |
1109 const void* upper_bound) | 1046 const void* upper_bound) |
1110 : shadow_(shadow), recursive_(recursive), lower_index_(0), upper_index_(0), | 1047 : shadow_(shadow), |
1111 shadow_cursor_(nullptr), nesting_depth_(0) { | 1048 lower_index_(0), |
| 1049 upper_index_(0), |
| 1050 shadow_cursor_(nullptr) { |
1112 DCHECK_NE(static_cast<Shadow*>(nullptr), shadow); | 1051 DCHECK_NE(static_cast<Shadow*>(nullptr), shadow); |
1113 DCHECK_LE(Shadow::kAddressLowerBound, reinterpret_cast<size_t>(lower_bound)); | 1052 DCHECK_LE(Shadow::kAddressLowerBound, reinterpret_cast<size_t>(lower_bound)); |
1114 | 1053 |
1115 // Get the bounds as shadow indices, being careful to deal with overflow | 1054 // Get the bounds as shadow indices, being careful to deal with overflow |
1116 // of |upper_bound|. | 1055 // of |upper_bound|. |
1117 lower_index_ = reinterpret_cast<uintptr_t>(lower_bound) >> kShadowRatioLog; | 1056 lower_index_ = reinterpret_cast<uintptr_t>(lower_bound) >> kShadowRatioLog; |
1118 upper_index_ = reinterpret_cast<size_t>(::common::AlignUp( | 1057 upper_index_ = reinterpret_cast<size_t>(::common::AlignUp( |
1119 reinterpret_cast<const uint8_t*>(upper_bound), kShadowRatio)); | 1058 reinterpret_cast<const uint8_t*>(upper_bound), kShadowRatio)); |
1120 upper_index_--; | 1059 upper_index_--; |
1121 upper_index_ >>= kShadowRatioLog; | 1060 upper_index_ >>= kShadowRatioLog; |
1122 upper_index_++; | 1061 upper_index_++; |
1123 | 1062 |
1124 DCHECK_LE(lower_index_, upper_index_); | 1063 DCHECK_LE(lower_index_, upper_index_); |
1125 DCHECK_GE(shadow->length(), upper_index_ - lower_index_); | 1064 DCHECK_GE(shadow->length(), upper_index_ - lower_index_); |
1126 | 1065 |
1127 Reset(); | 1066 Reset(); |
1128 } | 1067 } |
1129 | 1068 |
1130 void ShadowWalker::Reset() { | 1069 void ShadowWalker::Reset() { |
1131 nesting_depth_ = -1; | |
1132 shadow_cursor_ = shadow_->shadow() + lower_index_; | 1070 shadow_cursor_ = shadow_->shadow() + lower_index_; |
1133 } | 1071 } |
1134 | 1072 |
1135 bool ShadowWalker::Next(BlockInfo* info) { | 1073 bool ShadowWalker::Next(BlockInfo* info) { |
1136 DCHECK_NE(static_cast<BlockInfo*>(NULL), info); | 1074 DCHECK_NE(static_cast<BlockInfo*>(NULL), info); |
1137 | 1075 |
1138 auto shadow_upper_bound = shadow_->shadow() + upper_index_; | 1076 auto shadow_upper_bound = shadow_->shadow() + upper_index_; |
1139 | 1077 |
1140 while (shadow_cursor_ < shadow_upper_bound) { | 1078 while (shadow_cursor_ < shadow_upper_bound) { |
1141 // Skip uncommitted ranges of memory. This is possible when using a sparse | 1079 // Skip uncommitted ranges of memory. This is possible when using a sparse |
(...skipping 26 matching lines...) Expand all Loading... |
1168 } else { | 1106 } else { |
1169 end_of_region = std::min(shadow_upper_bound, end_of_region); | 1107 end_of_region = std::min(shadow_upper_bound, end_of_region); |
1170 } | 1108 } |
1171 | 1109 |
1172 // Scan this committed portion of the shadow. | 1110 // Scan this committed portion of the shadow. |
1173 while (shadow_cursor_ < end_of_region) { | 1111 while (shadow_cursor_ < end_of_region) { |
1174 uint8_t marker = *shadow_cursor_; | 1112 uint8_t marker = *shadow_cursor_; |
1175 | 1113 |
1176 // Update the nesting depth when block end markers are encountered. | 1114 // Update the nesting depth when block end markers are encountered. |
1177 if (ShadowMarkerHelper::IsBlockEnd(marker)) { | 1115 if (ShadowMarkerHelper::IsBlockEnd(marker)) { |
1178 DCHECK_LE(0, nesting_depth_); | |
1179 --nesting_depth_; | |
1180 ++shadow_cursor_; | 1116 ++shadow_cursor_; |
1181 continue; | 1117 continue; |
1182 } | 1118 } |
1183 | 1119 |
1184 // Look for a block start marker. | 1120 // Look for a block start marker. |
1185 if (ShadowMarkerHelper::IsBlockStart(marker)) { | 1121 if (ShadowMarkerHelper::IsBlockStart(marker)) { |
1186 // Update the nesting depth when block start bytes are encountered. | 1122 // This can only fail if the shadow memory is malformed. |
1187 ++nesting_depth_; | 1123 size_t block_index = shadow_cursor_ - shadow_->shadow(); |
| 1124 void* block_address = |
| 1125 reinterpret_cast<void*>(block_index << kShadowRatioLog); |
| 1126 CHECK(shadow_->BlockInfoFromShadow(block_address, info)); |
1188 | 1127 |
1189 // Non-nested blocks should only be encountered at depth 0. | 1128 // We skip directly to the end marker. |
1190 bool is_nested = ShadowMarkerHelper::IsNestedBlockStart(marker); | 1129 auto block_end = |
1191 DCHECK(is_nested || nesting_depth_ == 0); | 1130 reinterpret_cast<const uint8_t*>(info->header) + info->block_size; |
| 1131 shadow_cursor_ = shadow_->GetShadowMemoryForAddress(block_end) - 1; |
1192 | 1132 |
1193 // Determine if the block is to be reported. | 1133 // A block has been found and its |info| is parsed. Return to the |
1194 if (!is_nested || recursive_) { | 1134 // caller. |
1195 // This can only fail if the shadow memory is malformed. | 1135 return true; |
1196 size_t block_index = shadow_cursor_ - shadow_->shadow(); | |
1197 void* block_address = reinterpret_cast<void*>( | |
1198 block_index << kShadowRatioLog); | |
1199 CHECK(shadow_->BlockInfoFromShadow(block_address, info)); | |
1200 | |
1201 // In a recursive descent we have to process body contents. | |
1202 if (recursive_) { | |
1203 // Jump straight to the body of the nested block. | |
1204 shadow_cursor_ = shadow_->GetShadowMemoryForAddress( | |
1205 info->body); | |
1206 } else { | |
1207 // Otherwise we can skip the body of the block we just reported. | |
1208 // We skip directly to the end marker (but not past it so that depth | |
1209 // bookkeeping works properly). | |
1210 auto block_end = reinterpret_cast<const uint8_t*>(info->header) + | |
1211 info->block_size; | |
1212 shadow_cursor_ = shadow_->GetShadowMemoryForAddress(block_end) - 1; | |
1213 } | |
1214 | |
1215 // A block has been found and its |info| is parsed. Return to the | |
1216 // caller. | |
1217 return true; | |
1218 } | |
1219 } | 1136 } |
1220 | 1137 |
1221 // Advance the shadow cursor. | 1138 // Advance the shadow cursor. |
1222 ++shadow_cursor_; | 1139 ++shadow_cursor_; |
1223 } // while (shadow_cursor_ < end_of_region) | 1140 } // while (shadow_cursor_ < end_of_region) |
1224 } | 1141 } |
1225 | 1142 |
1226 return false; | 1143 return false; |
1227 } | 1144 } |
1228 | 1145 |
1229 } // namespace asan | 1146 } // namespace asan |
1230 } // namespace agent | 1147 } // namespace agent |
OLD | NEW |