CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
138 lines
4.6 KiB
C++
138 lines
4.6 KiB
C++
//===------------------------ nsan_platform.h -------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Platform specific information for NSan.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef NSAN_PLATFORM_H
|
|
#define NSAN_PLATFORM_H
|
|
|
|
namespace __nsan {
|
|
|
|
// NSan uses two regions of memory to store information:
|
|
// - 'shadow memory' stores the shadow copies of numerical values stored in
|
|
// application memory.
|
|
// - 'shadow types' is used to determine which value type each byte of memory
|
|
// belongs to. This makes sure that we always know whether a shadow value is
|
|
// valid. Shadow values may be tampered with using access through other
|
|
// pointer types (type punning). Each byte stores:
|
|
// - bit 1-0: whether the corresponding value is of unknown (00),
|
|
// float (01), double (10), or long double (11) type.
|
|
// - bit 5-2: the index of this byte in the value, or 0000 if type is
|
|
// unknown.
|
|
// This allows handling unaligned loat load/stores by checking that a load
|
|
// with a given alignment corresponds to the alignment of the store.
|
|
// Any store of a non-floating point type invalidates the corresponding
|
|
// bytes, so that subsequent overlapping loads (aligned or not) know that
|
|
// the corresponding shadow value is no longer valid.
|
|
|
|
// On Linux/x86_64, memory is laid out as follows:
|
|
//
|
|
// +--------------------+ 0x800000000000 (top of memory)
|
|
// | application memory |
|
|
// +--------------------+ 0x700000008000 (kAppAddr)
|
|
// | |
|
|
// | unused |
|
|
// | |
|
|
// +--------------------+ 0x440000008000
|
|
// | allocator |
|
|
// +--------------------+ 0x400000000000 (kHeapMemBeg)
|
|
// | shadow memory |
|
|
// +--------------------+ 0x200000000000 (kShadowAddr)
|
|
// | shadow types |
|
|
// +--------------------+ 0x100000000000 (kTypesAddr)
|
|
// | reserved by kernel |
|
|
// +--------------------+ 0x000000000000
|
|
//
|
|
//
|
|
// To derive a shadow memory address from an application memory address,
|
|
// bits 44-46 are cleared to bring the address into the range
|
|
// [0x000000000000,0x100000000000). We scale to account for the fact that a
|
|
// shadow value takes twice as much space as the original value.
|
|
// Then we add kShadowAddr to put the shadow relative offset into the shadow
|
|
// memory. See getShadowAddrFor().
|
|
// The process is similar for the shadow types.
|
|
|
|
// The ratio of app to shadow memory.
|
|
enum { kShadowScale = 2 };
|
|
|
|
// The original value type of a byte in app memory. Uses LLVM terminology:
|
|
// https://llvm.org/docs/LangRef.html#floating-point-types
|
|
// FIXME: support half and bfloat.
|
|
enum ValueType {
|
|
kUnknownValueType = 0,
|
|
kFloatValueType = 1, // LLVM float, shadow type double.
|
|
kDoubleValueType = 2, // LLVM double, shadow type fp128.
|
|
kFp80ValueType = 3, // LLVM x86_fp80, shadow type fp128.
|
|
};
|
|
|
|
// The size of ValueType encoding, in bits.
|
|
enum {
|
|
kValueSizeSizeBits = 2,
|
|
};
|
|
|
|
#if defined(__x86_64__)
|
|
struct Mapping {
|
|
// FIXME: kAppAddr == 0x700000000000 ?
|
|
static const uptr kAppAddr = 0x700000008000;
|
|
static const uptr kHeapMemBeg = 0x400000000000;
|
|
static const uptr kShadowAddr = 0x200000000000;
|
|
static const uptr kTypesAddr = 0x100000000000;
|
|
static const uptr kShadowMask = ~0x700000000000;
|
|
};
|
|
#else
|
|
#error "NSan not supported for this platform!"
|
|
#endif
|
|
|
|
enum MappingType {
|
|
MAPPING_APP_ADDR,
|
|
MAPPING_ALLOCATOR_ADDR,
|
|
MAPPING_SHADOW_ADDR,
|
|
MAPPING_TYPES_ADDR,
|
|
MAPPING_SHADOW_MASK
|
|
};
|
|
|
|
template <typename Mapping, int Type> uptr MappingImpl() {
|
|
switch (Type) {
|
|
case MAPPING_APP_ADDR:
|
|
return Mapping::kAppAddr;
|
|
case MAPPING_ALLOCATOR_ADDR:
|
|
return Mapping::kHeapMemBeg;
|
|
case MAPPING_SHADOW_ADDR:
|
|
return Mapping::kShadowAddr;
|
|
case MAPPING_TYPES_ADDR:
|
|
return Mapping::kTypesAddr;
|
|
case MAPPING_SHADOW_MASK:
|
|
return Mapping::kShadowMask;
|
|
}
|
|
}
|
|
|
|
template <int Type> uptr MappingArchImpl() {
|
|
return MappingImpl<Mapping, Type>();
|
|
}
|
|
|
|
ALWAYS_INLINE
|
|
uptr AppAddr() { return MappingArchImpl<MAPPING_APP_ADDR>(); }
|
|
|
|
ALWAYS_INLINE
|
|
uptr AllocatorAddr() { return MappingArchImpl<MAPPING_ALLOCATOR_ADDR>(); }
|
|
|
|
ALWAYS_INLINE
|
|
uptr ShadowAddr() { return MappingArchImpl<MAPPING_SHADOW_ADDR>(); }
|
|
|
|
ALWAYS_INLINE
|
|
uptr TypesAddr() { return MappingArchImpl<MAPPING_TYPES_ADDR>(); }
|
|
|
|
ALWAYS_INLINE
|
|
uptr ShadowMask() { return MappingArchImpl<MAPPING_SHADOW_MASK>(); }
|
|
|
|
} // end namespace __nsan
|
|
|
|
#endif
|