1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (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
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Contains the implementation details of the templated functions of Asan's
16 : // shadow memory. See 'shadow.h' for more information. This file is not
17 : // meant to be included directly, but is brought in by shadow.h.
18 : #ifndef SYZYGY_AGENT_ASAN_SHADOW_IMPL_H_
19 : #define SYZYGY_AGENT_ASAN_SHADOW_IMPL_H_
20 :
21 : template <typename type>
22 : bool Shadow::GetNullTerminatedArraySize(const void* addr,
23 : size_t max_size,
24 E : size_t* size) const {
25 E : DCHECK_NE(reinterpret_cast<const void*>(NULL), addr);
26 E : DCHECK_NE(reinterpret_cast<size_t*>(NULL), size);
27 :
28 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
29 E : const type* addr_value = reinterpret_cast<const type*>(addr);
30 E : index >>= 3;
31 E : *size = 0;
32 :
33 E : if (index > length_)
34 i : return false;
35 :
36 : // Scan the input array 8 bytes at a time until we've found a NULL value or
37 : // we've reached the end of an accessible memory block.
38 : // TODO(sebmarchand): Look into doing this more efficiently.
39 E : while (true) {
40 E : uint8_t shadow = shadow_[index++];
41 E : if (ShadowMarkerHelper::IsRedzone(shadow))
42 E : return false;
43 :
44 E : uint8_t max_index = shadow ? shadow : kShadowRatio;
45 E : DCHECK_EQ(0U, max_index % sizeof(type));
46 E : max_index /= sizeof(type);
47 E : while (max_index-- > 0) {
48 E : (*size) += sizeof(type);
49 E : if (*size == max_size || *addr_value == 0)
50 E : return true;
51 E : addr_value++;
52 E : }
53 :
54 E : if (shadow != 0)
55 E : return false;
56 E : }
57 E : }
58 :
59 : namespace internal {
60 :
61 : template <typename AccessType>
62 E : const AccessType* AlignDown(const uint8_t* ptr) {
63 E : DCHECK(::common::IsPowerOfTwo(sizeof(AccessType)));
64 E : return reinterpret_cast<const AccessType*>(reinterpret_cast<uintptr_t>(ptr) &
65 : ~(sizeof(AccessType) - 1));
66 E : }
67 :
68 : template <typename AccessType>
69 E : const AccessType* AlignUp(const uint8_t* ptr) {
70 E : DCHECK(::common::IsPowerOfTwo(sizeof(AccessType)));
71 :
72 E : return reinterpret_cast<const AccessType*>(
73 : reinterpret_cast<uintptr_t>(ptr + sizeof(AccessType) - 1) &
74 : ~(sizeof(AccessType) - 1));
75 E : }
76 :
77 : // Returns true iff every byte in the range [@p start, @p end) is zero.
78 : // This function reads sizeof(AccessType) bytes at a time from memory at
79 : // natural alignment for AccessType. Note this may under- and over-read the
80 : // provided buffer by sizeof(AccessType)-1 bytes, but will never cross
81 : // sizeof(AccessType) boundary. The implementation is intended to allow the
82 : // compiler to inline it to the usage.
83 : // @param start the first byte to test.
84 : // @param end the byte after the last byte to test.
85 : // @returns true iff every byte from @p *start to @p *(end - 1) is zero.
86 : // @note this function is templatized to allow easily performance testing
87 : // it with different AccessType parameters.
88 : template <typename AccessType>
89 E : bool IsZeroBufferImpl(const uint8_t* start_in, const uint8_t* end_in) {
90 E : if (start_in == end_in)
91 E : return true;
92 :
93 : // Round the start address downwards, and the end address upwards.
94 E : const AccessType* start = AlignDown<AccessType>(start_in);
95 E : const AccessType* end = AlignUp<AccessType>(end_in);
96 :
97 : // Assuming start_in != end_in the alignment should leave us at least one
98 : // element to check.
99 E : DCHECK_NE(start, end);
100 E : AccessType val = *start;
101 :
102 : // Mask out the bytes read due to starting alignment.
103 E : const AccessType kMask = static_cast<AccessType>(-1LL);
104 E : val &= kMask << ((start_in - reinterpret_cast<const uint8_t*>(start)) * 8);
105 E : ++start;
106 E : while (start != end) {
107 E : if (val != 0U)
108 E : return false;
109 E : val = *start++;
110 E : }
111 :
112 : // Mask out the bytes read due to end alignment.
113 E : val &= kMask >> ((reinterpret_cast<const uint8_t*>(end) - end_in) * 8);
114 E : if (val != 0U)
115 E : return false;
116 :
117 E : return true;
118 E : }
119 :
120 : } // namespace internal
121 :
122 : #endif // SYZYGY_AGENT_ASAN_SHADOW_IMPL_H_
|