blob: 8f3cd33dcea9dbc8f51de9a047978dac0ea682db [file] [log] [blame]
// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "syzygy/agent/asan/shadow_marker.h"
#include "base/logging.h"
namespace agent {
namespace asan {
namespace {
// Some constants related to the structure of shadow marker values.
static const uint8 kActiveBit = 0x20;
static const uint8 kBlockEndNestedBit = 0x01;
static const uint8 kBlockStartDataMask = 0x7;
static const uint8 kBlockStartNestedBit = 0x08;
static const uint8 kFirstNibble = 0xF0;
static const uint8 kRedzoneBit = 0x80;
// ShadowMarker name generator. This maps an enumeration value to a name via
// template specialization.
template<size_t kIndex> struct ShadowMarkerNameGenerator {
static const uintptr_t kName = 0;
};
#define SHADOW_MARKER_NAME_GENERATOR_MACRO(name, value) \
template<> struct ShadowMarkerNameGenerator<value> { \
static const char* kName; \
}; \
const char* ShadowMarkerNameGenerator<value>::kName = \
_STRINGIZE(name);
SHADOW_MARKER_GENERATOR(SHADOW_MARKER_NAME_GENERATOR_MACRO)
#undef SHADOW_MARKER_NAME_GENERATOR_MACRO
} // namespace
// This generates an array of shadow marker names, populating valid markers
// with their names as defined by the template specialization above. Invalid
// markers map to NULL as defined by the base template.
#define ITERATE_2(F, base) F(base) F(base + 1)
#define ITERATE_4(F, base) ITERATE_2(F, base) ITERATE_2(F, base + 2)
#define ITERATE_8(F, base) ITERATE_4(F, base) ITERATE_4(F, base + 4)
#define ITERATE_16(F, base) ITERATE_8(F, base) ITERATE_8(F, base + 8)
#define ITERATE_32(F, base) ITERATE_16(F, base) ITERATE_16(F, base + 16)
#define ITERATE_64(F, base) ITERATE_32(F, base) ITERATE_32(F, base + 32)
#define ITERATE_128(F, base) ITERATE_64(F, base) ITERATE_64(F, base + 64)
#define ITERATE_256(F) ITERATE_128(F, 0) ITERATE_128(F, 128)
#define GET_SHADOW_MARKER_STRING_PTR(index) \
reinterpret_cast<const char*>(ShadowMarkerNameGenerator<index>::kName),
const char* kShadowMarkerNames[256] = {
ITERATE_256(GET_SHADOW_MARKER_STRING_PTR)
};
#undef GET_SHADOW_MARKER_STRING_PTR
#undef ITERATE_256
#undef ITERATE_128
#undef ITERATE_64
#undef ITERATE_32
#undef ITERATE_16
#undef ITERATE_8
#undef ITERATE_4
#undef ITERATE_2
bool ShadowMarkerHelper::IsRedzone(ShadowMarkerValue marker) {
return (marker.value & kRedzoneBit) == kRedzoneBit;
}
bool ShadowMarkerHelper::IsActiveBlock(ShadowMarkerValue marker) {
return marker.value == kHeapLeftPaddingMarker ||
marker.value == kHeapRightPaddingMarker ||
marker.value == kHeapFreedMarker ||
IsActiveBlockStart(marker) ||
IsActiveBlockEnd(marker);
}
bool ShadowMarkerHelper::IsHistoricBlock(ShadowMarkerValue marker) {
return marker.value == kHeapHistoricLeftPaddingMarker ||
marker.value == kHeapHistoricRightPaddingMarker ||
marker.value == kHeapHistoricFreedMarker ||
IsHistoricBlockStart(marker) ||
IsHistoricBlockEnd(marker);
}
bool ShadowMarkerHelper::IsBlock(ShadowMarkerValue marker) {
return IsActiveBlock(marker) || IsHistoricBlock(marker);
}
bool ShadowMarkerHelper::IsActiveBlockStart(ShadowMarkerValue marker) {
return (marker.value & kFirstNibble) == kHeapBlockStartMarker0;
}
bool ShadowMarkerHelper::IsHistoricBlockStart(ShadowMarkerValue marker) {
return (marker.value & kFirstNibble) == kHeapHistoricBlockStartMarker0;
}
bool ShadowMarkerHelper::IsBlockStart(ShadowMarkerValue marker) {
static const uint8 kMask = kFirstNibble ^ kActiveBit;
return (marker.value & kMask) == kHeapHistoricBlockStartMarker0;
}
bool ShadowMarkerHelper::IsNestedBlockStart(ShadowMarkerValue marker) {
if (!IsBlockStart(marker))
return false;
return (marker.value & kBlockStartNestedBit) == kBlockStartNestedBit;
}
uint8 ShadowMarkerHelper::GetBlockStartData(ShadowMarkerValue marker) {
return marker.value & kBlockStartDataMask;
}
bool ShadowMarkerHelper::IsActiveBlockEnd(ShadowMarkerValue marker) {
return (marker.value & ~kBlockEndNestedBit) ==
kHeapBlockEndMarker;
}
bool ShadowMarkerHelper::IsHistoricBlockEnd(ShadowMarkerValue marker) {
return (marker.value & ~kBlockEndNestedBit) ==
kHeapHistoricBlockEndMarker;
}
bool ShadowMarkerHelper::IsBlockEnd(ShadowMarkerValue marker) {
// Block end markers have arbitrary values for the active bit
// and the block end nested bit.
static const uint8 kMask = ~(kActiveBit | kBlockEndNestedBit);
return (marker.value & kMask) == kHeapHistoricBlockEndMarker;
}
bool ShadowMarkerHelper::IsNestedBlockEnd(ShadowMarkerValue marker) {
if (!IsBlockEnd(marker))
return false;
return (marker.value & kBlockEndNestedBit) == kBlockEndNestedBit;
}
bool ShadowMarkerHelper::IsHistoricLeftRedzone(ShadowMarkerValue marker) {
return marker.value == kHeapHistoricLeftPaddingMarker ||
IsHistoricBlockStart(marker);
}
bool ShadowMarkerHelper::IsActiveLeftRedzone(ShadowMarkerValue marker) {
return marker.value == kHeapLeftPaddingMarker ||
IsActiveBlockStart(marker);
}
bool ShadowMarkerHelper::IsLeftRedzone(ShadowMarkerValue marker) {
return (marker.value & ~kActiveBit) == kHeapHistoricLeftPaddingMarker ||
IsBlockStart(marker);
}
bool ShadowMarkerHelper::IsHistoricRightRedzone(ShadowMarkerValue marker) {
return marker.value == kHeapHistoricRightPaddingMarker ||
IsHistoricBlockEnd(marker);
}
bool ShadowMarkerHelper::IsActiveRightRedzone(ShadowMarkerValue marker) {
return marker.value == kHeapRightPaddingMarker ||
IsActiveBlockEnd(marker);
}
bool ShadowMarkerHelper::IsRightRedzone(ShadowMarkerValue marker) {
return (marker.value & ~kActiveBit) == kHeapHistoricRightPaddingMarker ||
IsBlockEnd(marker);
}
ShadowMarker ShadowMarkerHelper::ToHistoric(ShadowMarkerValue marker) {
DCHECK(IsActiveBlock(marker));
return static_cast<ShadowMarker>(marker.value & ~kActiveBit);
}
ShadowMarker ShadowMarkerHelper::BuildBlockStart(
bool active, bool nested, uint8 data) {
DCHECK_EQ(0, data & ~kBlockStartDataMask);
uint8 marker = kHeapHistoricBlockStartMarker0;
if (active)
marker |= kActiveBit;
if (nested)
marker |= kBlockStartNestedBit;
marker |= data;
return static_cast<ShadowMarker>(marker);
}
ShadowMarker ShadowMarkerHelper::BuildBlockEnd(bool active, bool nested) {
uint8 marker = kHeapHistoricBlockEndMarker;
if (active)
marker |= kActiveBit;
if (nested)
marker |= kBlockEndNestedBit;
return static_cast<ShadowMarker>(marker);
}
} // namespace asan
} // namespace agent