Path: blob/main/contrib/llvm-project/compiler-rt/lib/nsan/nsan_platform.h
35233 views
//===------------------------ nsan_platform.h -------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Platform specific information for NSan.9//10//===----------------------------------------------------------------------===//1112#ifndef NSAN_PLATFORM_H13#define NSAN_PLATFORM_H1415namespace __nsan {1617// NSan uses two regions of memory to store information:18// - 'shadow memory' stores the shadow copies of numerical values stored in19// application memory.20// - 'shadow types' is used to determine which value type each byte of memory21// belongs to. This makes sure that we always know whether a shadow value is22// valid. Shadow values may be tampered with using access through other23// pointer types (type punning). Each byte stores:24// - bit 1-0: whether the corresponding value is of unknown (00),25// float (01), double (10), or long double (11) type.26// - bit 5-2: the index of this byte in the value, or 0000 if type is27// unknown.28// This allows handling unaligned loat load/stores by checking that a load29// with a given alignment corresponds to the alignment of the store.30// Any store of a non-floating point type invalidates the corresponding31// bytes, so that subsequent overlapping loads (aligned or not) know that32// the corresponding shadow value is no longer valid.3334// On Linux/x86_64, memory is laid out as follows:35//36// +--------------------+ 0x800000000000 (top of memory)37// | application memory |38// +--------------------+ 0x700000008000 (kAppAddr)39// | |40// | unused |41// | |42// +--------------------+ 0x400000000000 (kUnusedAddr)43// | shadow memory |44// +--------------------+ 0x200000000000 (kShadowAddr)45// | shadow types |46// +--------------------+ 0x100000000000 (kTypesAddr)47// | reserved by kernel |48// +--------------------+ 0x00000000000049//50//51// To derive a shadow memory address from an application memory address,52// bits 44-46 are cleared to bring the address into the range53// [0x000000000000,0x100000000000). We scale to account for the fact that a54// shadow value takes twice as much space as the original value.55// Then we add kShadowAddr to put the shadow relative offset into the shadow56// memory. See getShadowAddrFor().57// The process is similar for the shadow types.5859// The ratio of app to shadow memory.60enum { kShadowScale = 2 };6162// The original value type of a byte in app memory. Uses LLVM terminology:63// https://llvm.org/docs/LangRef.html#floating-point-types64// FIXME: support half and bfloat.65enum ValueType {66kUnknownValueType = 0,67kFloatValueType = 1, // LLVM float, shadow type double.68kDoubleValueType = 2, // LLVM double, shadow type fp128.69kFp80ValueType = 3, // LLVM x86_fp80, shadow type fp128.70};7172// The size of ValueType encoding, in bits.73enum {74kValueSizeSizeBits = 2,75};7677#if defined(__x86_64__)78struct Mapping {79// FIXME: kAppAddr == 0x700000000000 ?80static const uptr kAppAddr = 0x700000008000;81static const uptr kUnusedAddr = 0x400000000000;82static const uptr kShadowAddr = 0x200000000000;83static const uptr kTypesAddr = 0x100000000000;84static const uptr kShadowMask = ~0x700000000000;85};86#else87#error "NSan not supported for this platform!"88#endif8990enum MappingType {91MAPPING_APP_ADDR,92MAPPING_UNUSED_ADDR,93MAPPING_SHADOW_ADDR,94MAPPING_TYPES_ADDR,95MAPPING_SHADOW_MASK96};9798template <typename Mapping, int Type> uptr MappingImpl() {99switch (Type) {100case MAPPING_APP_ADDR:101return Mapping::kAppAddr;102case MAPPING_UNUSED_ADDR:103return Mapping::kUnusedAddr;104case MAPPING_SHADOW_ADDR:105return Mapping::kShadowAddr;106case MAPPING_TYPES_ADDR:107return Mapping::kTypesAddr;108case MAPPING_SHADOW_MASK:109return Mapping::kShadowMask;110}111}112113template <int Type> uptr MappingArchImpl() {114return MappingImpl<Mapping, Type>();115}116117ALWAYS_INLINE118uptr AppAddr() { return MappingArchImpl<MAPPING_APP_ADDR>(); }119120ALWAYS_INLINE121uptr UnusedAddr() { return MappingArchImpl<MAPPING_UNUSED_ADDR>(); }122123ALWAYS_INLINE124uptr ShadowAddr() { return MappingArchImpl<MAPPING_SHADOW_ADDR>(); }125126ALWAYS_INLINE127uptr TypesAddr() { return MappingArchImpl<MAPPING_TYPES_ADDR>(); }128129ALWAYS_INLINE130uptr ShadowMask() { return MappingArchImpl<MAPPING_SHADOW_MASK>(); }131132} // end namespace __nsan133134#endif135136137