Author: anoopkg6 Date: 2026-01-19T15:28:34+01:00 New Revision: fb953283af3fb246f815961ad2fbe7938936c7f5
URL: https://github.com/llvm/llvm-project/commit/fb953283af3fb246f815961ad2fbe7938936c7f5 DIFF: https://github.com/llvm/llvm-project/commit/fb953283af3fb246f815961ad2fbe7938936c7f5.diff LOG: [dfsan] Add dataflow sanitizer support for SystemZ (#168991) Add SystemZ specific changes for dataflow sanitizer on top of following two common code changes i) Fix Endianness issue [#162881](https://github.com/llvm/llvm-project/pull/162881) ii) Fix ShadowAddress computation [#162864](https://github.com/llvm/llvm-project/pull/162864[](url)) See conversation in original pr#[#162195](https://github.com/llvm/llvm-project/pull/162195) Added: Modified: clang/lib/Driver/ToolChains/Linux.cpp compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake compiler-rt/lib/dfsan/dfsan_allocator.cpp compiler-rt/lib/dfsan/dfsan_custom.cpp compiler-rt/lib/dfsan/dfsan_platform.h compiler-rt/test/dfsan/custom.cpp compiler-rt/test/dfsan/lit.cfg.py compiler-rt/test/dfsan/origin_endianness.c compiler-rt/test/dfsan/pair.cpp compiler-rt/test/dfsan/struct.c llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp Removed: ################################################################################ diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index d525b417b4eae..f62c209eb847c 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -927,7 +927,7 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::KernelAddress; Res |= SanitizerKind::Vptr; Res |= SanitizerKind::SafeStack; - if (IsX86_64 || IsMIPS64 || IsAArch64 || IsLoongArch64) + if (IsX86_64 || IsMIPS64 || IsAArch64 || IsLoongArch64 || IsSystemZ) Res |= SanitizerKind::DataFlow; if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 || IsRISCV64 || IsSystemZ || IsHexagon || IsLoongArch64) diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index 0cae5da26c3e7..c2de0d0f652e8 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -45,7 +45,8 @@ set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON} ${LOONGARCH64}) set(ALL_ASAN_ABI_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM64_32}) -set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${LOONGARCH64}) +set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${LOONGARCH64} + ${S390X}) set(ALL_RTSAN_SUPPORTED_ARCH ${X86_64} ${ARM64}) if(ANDROID) diff --git a/compiler-rt/lib/dfsan/dfsan_allocator.cpp b/compiler-rt/lib/dfsan/dfsan_allocator.cpp index 160b1a64d8f6f..c5583288f9619 100644 --- a/compiler-rt/lib/dfsan/dfsan_allocator.cpp +++ b/compiler-rt/lib/dfsan/dfsan_allocator.cpp @@ -44,17 +44,26 @@ struct DFsanMapUnmapCallback { // duplicated as MappingDesc::ALLOCATOR in dfsan_platform.h. #if defined(__aarch64__) const uptr kAllocatorSpace = 0xE00000000000ULL; +const uptr kAllocatorSpaceSize = 0x40000000000; // 4T. +#elif defined(__s390x__) +const uptr kAllocatorSpace = 0x440000000000ULL; +const uptr kAllocatorSpaceSize = 0x020000000000; // 2T. #else const uptr kAllocatorSpace = 0x700000000000ULL; +const uptr kAllocatorSpaceSize = 0x40000000000; // 4T. #endif +#if defined(__s390x__) +const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G. +#else const uptr kMaxAllowedMallocSize = 1ULL << 40; +#endif struct AP64 { // Allocator64 parameters. Deliberately using a short name. static const uptr kSpaceBeg = kAllocatorSpace; - static const uptr kSpaceSize = 0x40000000000; // 4T. + static const uptr kSpaceSize = kAllocatorSpaceSize; static const uptr kMetadataSize = sizeof(Metadata); - typedef DefaultSizeClassMap SizeClassMap; - typedef DFsanMapUnmapCallback MapUnmapCallback; + using SizeClassMap = DefaultSizeClassMap; + using MapUnmapCallback = DFsanMapUnmapCallback; static const uptr kFlags = 0; using AddressSpaceView = LocalAddressSpaceView; }; diff --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp index dbc00d7ac3ea3..b060e5c56edbe 100644 --- a/compiler-rt/lib/dfsan/dfsan_custom.cpp +++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp @@ -2332,7 +2332,20 @@ static int format_buffer(char *str, size_t size, const char *fmt, case 'g': case 'G': if (*(formatter.fmt_cur - 1) == 'L') { +#if defined(__s390x__) + // SystemZ treats float128 argument as an aggregate type and copies + // shadow and Origin to passed argument temporary. But passed + // argument va_labels and va_origins are zero. Here. we get + // Shadow/Origin corresponding to in-memory argument and update + // va_labels and va_origins. + long double* arg = va_arg(ap, long double*); + *va_labels = *shadow_for(arg); + if (va_origins != nullptr) + *va_origins = *origin_for(arg); + retval = formatter.format(*arg); +#else retval = formatter.format(va_arg(ap, long double)); +#endif } else { retval = formatter.format(va_arg(ap, double)); } diff --git a/compiler-rt/lib/dfsan/dfsan_platform.h b/compiler-rt/lib/dfsan/dfsan_platform.h index 01f0de47d960d..59c39cbe3b75e 100644 --- a/compiler-rt/lib/dfsan/dfsan_platform.h +++ b/compiler-rt/lib/dfsan/dfsan_platform.h @@ -67,6 +67,20 @@ const MappingDesc kMemoryLayout[] = { }; # define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL) # define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL) +# elif SANITIZER_LINUX && SANITIZER_S390_64 +const MappingDesc kMemoryLayout[] = { + {0x000000000000ULL, 0x040000000000ULL, MappingDesc::APP, "app-low"}, + {0x040000000000ULL, 0x080000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x080000000000ULL, 0x180000000000ULL, MappingDesc::SHADOW, "shadow"}, + {0x180000000000ULL, 0x1C0000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x1C0000000000ULL, 0x2C0000000000ULL, MappingDesc::ORIGIN, "origin"}, + {0x2C0000000000ULL, 0x440000000000ULL, MappingDesc::INVALID, "invalid"}, + {0x440000000000ULL, 0x460000000000ULL, MappingDesc::ALLOCATOR, "allocator"}, + {0x460000000000ULL, 0x500000000000ULL, MappingDesc::APP, "app-high"}}; + +# define MEM_TO_SHADOW(mem) \ + ((((uptr)(mem)) & ~0xC00000000000ULL) + 0x080000000000ULL) +# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x140000000000ULL) # else // All of the following configurations are supported. diff --git a/compiler-rt/test/dfsan/custom.cpp b/compiler-rt/test/dfsan/custom.cpp index 873af5cd934e2..b4d6b186cb61e 100644 --- a/compiler-rt/test/dfsan/custom.cpp +++ b/compiler-rt/test/dfsan/custom.cpp @@ -2240,7 +2240,7 @@ void test_sscanf() { strcpy(input_buf, "-559038737"); test_sscanf_chunk(-559038737, "%d", input_ptr, 1); strcpy(input_buf, "3735928559"); - test_sscanf_chunk(3735928559, "%u", input_ptr, 1); + test_sscanf_chunk(3735928559, "%lu", input_ptr, 1); strcpy(input_buf, "12345"); test_sscanf_chunk(12345, "%i", input_ptr, 1); strcpy(input_buf, "0751"); diff --git a/compiler-rt/test/dfsan/lit.cfg.py b/compiler-rt/test/dfsan/lit.cfg.py index b26ff3e367942..ec07db531461d 100644 --- a/compiler-rt/test/dfsan/lit.cfg.py +++ b/compiler-rt/test/dfsan/lit.cfg.py @@ -10,6 +10,9 @@ # Setup default compiler flags used with -fsanitize=dataflow option. clang_dfsan_cflags = ["-fsanitize=dataflow"] + [config.target_cflags] +# s390x arch needs -mbackchain to print stack backtrace of origin. +if config.target_arch == "s390x": + clang_dfsan_cflags.append("-mbackchain") clang_dfsan_cxxflags = config.cxx_mode_flags + clang_dfsan_cflags @@ -25,5 +28,8 @@ def build_invocation(compile_flags): config.suffixes = [".c", ".cpp"] # DataFlowSanitizer tests are currently supported on Linux only. -if not (config.target_os in ["Linux"] and config.target_arch in ["aarch64", "x86_64", "loongarch64"]): +if not ( + config.target_os in ["Linux"] + and config.target_arch in ["aarch64", "x86_64", "loongarch64", "s390x"] +): config.unsupported = True diff --git a/compiler-rt/test/dfsan/origin_endianness.c b/compiler-rt/test/dfsan/origin_endianness.c index a73dcda080e79..cd0b198017f57 100644 --- a/compiler-rt/test/dfsan/origin_endianness.c +++ b/compiler-rt/test/dfsan/origin_endianness.c @@ -16,10 +16,10 @@ __attribute__((noinline)) FULL_TYPE foo(FULL_TYPE a, FULL_TYPE b) { int main(int argc, char *argv[]) { FULL_TYPE a = 1; FULL_TYPE b = 10; - dfsan_set_label(4, (HALF_TYPE *)&a, sizeof(HALF_TYPE)); + dfsan_set_label(4, (HALF_TYPE *)&a + 1, sizeof(HALF_TYPE)); FULL_TYPE c = foo(a, b); dfsan_print_origin_trace(&c, NULL); - dfsan_print_origin_trace((HALF_TYPE *)&c, NULL); + dfsan_print_origin_trace((HALF_TYPE *)&c + 1, NULL); } // CHECK: Taint value 0x4 {{.*}} origin tracking () diff --git a/compiler-rt/test/dfsan/pair.cpp b/compiler-rt/test/dfsan/pair.cpp index 94bbfc72bc649..e3b3bccaf3182 100644 --- a/compiler-rt/test/dfsan/pair.cpp +++ b/compiler-rt/test/dfsan/pair.cpp @@ -6,6 +6,9 @@ #include <sanitizer/dfsan_interface.h> #include <utility> +// SystemZ identifies labels for struct elements precisely across all +// optimization labels. + __attribute__((noinline)) std::pair<int *, int> make_pair(int *p, int i) { return {p, i}; } @@ -65,7 +68,7 @@ void test_simple_constructors() { int i1 = pair1.second; int *ptr1 = pair1.first; -#ifdef O0 +#if defined(O0) && !defined(__s390x__) assert(dfsan_read_label(&i1, sizeof(i1)) == 10); assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 10); #else @@ -77,7 +80,7 @@ void test_simple_constructors() { int i2 = pair2.second; int *ptr2 = pair2.first; -#ifdef O0 +#if defined(O0) && !defined(__s390x__) assert(dfsan_read_label(&i2, sizeof(i2)) == 10); assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 10); #else @@ -89,7 +92,7 @@ void test_simple_constructors() { int i3 = pair3.second; int *ptr3 = pair3.first; -#ifdef O0 +#if defined(O0) && !defined(__s390x__) assert(dfsan_read_label(&i3, sizeof(i3)) == 10); assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 10); #else @@ -101,7 +104,7 @@ void test_simple_constructors() { int i4 = pair4.second; int *ptr4 = pair4.first; -#ifdef O0 +#if defined(O0) && !defined(__s390x__) assert(dfsan_read_label(&i4, sizeof(i4)) == 10); assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 10); #else @@ -139,7 +142,7 @@ void test_branches() { { std::pair<const char *, uint32_t> r = return_ptr_and_i32(q, res); -#ifdef O0 +#if defined(O0) && !defined(__s390x__) assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10); assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10); #else @@ -150,7 +153,7 @@ void test_branches() { { std::pair<const char *, uint64_t> r = return_ptr_and_i64(q, res); -#ifdef O0 +#if defined(O0) && !defined(__s390x__) assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10); assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10); #else diff --git a/compiler-rt/test/dfsan/struct.c b/compiler-rt/test/dfsan/struct.c index 7ba0016f7beee..fa976434a5ef4 100644 --- a/compiler-rt/test/dfsan/struct.c +++ b/compiler-rt/test/dfsan/struct.c @@ -4,6 +4,9 @@ #include <assert.h> #include <sanitizer/dfsan_interface.h> +// SystemZ identifies labels for struct elements precisely across all +// optimization labels. + typedef struct Pair { int i; char *ptr; @@ -47,7 +50,7 @@ int main(void) { dfsan_label i1_label = dfsan_read_label(&i1, sizeof(i1)); dfsan_label ptr1_label = dfsan_read_label(&ptr1, sizeof(ptr1)); -#if defined(O0) +#if defined(O0) && !defined(__s390x__) assert(i1_label == (i_label | ptr_label)); assert(ptr1_label == (i_label | ptr_label)); #else @@ -61,7 +64,7 @@ int main(void) { dfsan_label i2_label = dfsan_read_label(&i2, sizeof(i2)); dfsan_label ptr2_label = dfsan_read_label(&ptr2, sizeof(ptr2)); -#if defined(O0) +#if defined(O0) && !defined(__s390x__) assert(i2_label == (i_label | ptr_label)); assert(ptr2_label == (i_label | ptr_label)); #else @@ -75,7 +78,7 @@ int main(void) { dfsan_label i3_label = dfsan_read_label(&i3, sizeof(i3)); dfsan_label ptr3_label = dfsan_read_label(&ptr3, sizeof(ptr3)); -#if defined(O0) +#if defined(O0) && !defined(__s390x__) assert(i3_label == (i_label | ptr_label)); assert(ptr3_label == (i_label | ptr_label)); #else diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index e984ac46fca4a..7f63bf6b4941f 100644 --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -318,6 +318,14 @@ const MemoryMapParams Linux_LoongArch64_MemoryMapParams = { 0x100000000000, // OriginBase }; +// s390x Linux +const MemoryMapParams Linux_S390X_MemoryMapParams = { + 0xC00000000000, // AndMask + 0, // XorMask (not used) + 0x080000000000, // ShadowBase + 0x1C0000000000, // OriginBase +}; + namespace { class DFSanABIList { @@ -1146,6 +1154,9 @@ bool DataFlowSanitizer::initializeModule(Module &M) { case Triple::loongarch64: MapParams = &Linux_LoongArch64_MemoryMapParams; break; + case Triple::systemz: + MapParams = &Linux_S390X_MemoryMapParams; + break; default: report_fatal_error("unsupported architecture"); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
