From 57290f934abbb5c115efc067d68636ecb0741f1e Mon Sep 17 00:00:00 2001 From: Marcin Koscielnicki Date: Sat, 30 Apr 2016 09:57:34 +0000 Subject: [PATCH] [ASan] Add shadow offset for SystemZ. SystemZ on Linux currently has 53-bit address space. In theory, the hardware could support a full 64-bit address space, but that's not supported due to kernel limitations (it'd require 5-level page tables), and there are no plans for that. The default process layout stays within first 4TB of address space (to avoid creating 4-level page tables), so any offset >= (1 << 42) is fine. Let's use 1 << 52 here, ie. exactly half the address space. I've originally used 7 << 50 (uses top 1/8th of the address space), but ASan runtime assumes there's some space after the shadow area. While this is fixable, it's simpler to avoid the issue entirely. Also, I've originally wanted to have the shadow aligned to 1/8th the address space, so that we can use OR like X86 to assemble the offset. I no longer think it's a good idea, since using ADD enables us to load the constant just once and use it with register + register indexed addressing. Differential Revision: http://reviews.llvm.org/D19650 llvm-svn: 268161 --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index cea68dd..f2b5179 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -71,6 +71,7 @@ static const uint64_t kIOSSimShadowOffset64 = kDefaultShadowOffset64; static const uint64_t kSmallX86_64ShadowOffset = 0x7FFF8000; // < 2G. static const uint64_t kLinuxKasan_ShadowOffset64 = 0xdffffc0000000000; static const uint64_t kPPC64_ShadowOffset64 = 1ULL << 41; +static const uint64_t kSystemZ_ShadowOffset64 = 1ULL << 52; static const uint64_t kMIPS32_ShadowOffset32 = 0x0aaa0000; static const uint64_t kMIPS64_ShadowOffset64 = 1ULL << 37; static const uint64_t kAArch64_ShadowOffset64 = 1ULL << 36; @@ -351,6 +352,7 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize, bool IsLinux = TargetTriple.isOSLinux(); bool IsPPC64 = TargetTriple.getArch() == llvm::Triple::ppc64 || TargetTriple.getArch() == llvm::Triple::ppc64le; + bool IsSystemZ = TargetTriple.getArch() == llvm::Triple::systemz; bool IsX86 = TargetTriple.getArch() == llvm::Triple::x86; bool IsX86_64 = TargetTriple.getArch() == llvm::Triple::x86_64; bool IsMIPS32 = TargetTriple.getArch() == llvm::Triple::mips || @@ -381,6 +383,8 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize, } else { // LongSize == 64 if (IsPPC64) Mapping.Offset = kPPC64_ShadowOffset64; + else if (IsSystemZ) + Mapping.Offset = kSystemZ_ShadowOffset64; else if (IsFreeBSD) Mapping.Offset = kFreeBSD_ShadowOffset64; else if (IsLinux && IsX86_64) { @@ -406,8 +410,10 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize, // OR-ing shadow offset if more efficient (at least on x86) if the offset // is a power of two, but on ppc64 we have to use add since the shadow - // offset is not necessary 1/8-th of the address space. - Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 + // offset is not necessary 1/8-th of the address space. On SystemZ, + // we could OR the constant in a single instruction, but it's more + // efficient to load it once and use indexed addressing. + Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !(Mapping.Offset & (Mapping.Offset - 1)); return Mapping; -- 2.7.4