-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[dfsan] Add dataflow sanitizer support for SystemZ #168991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
and llvm#162864(Refer original pr#162195)
|
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-clang-driver Author: None (anoopkg6) ChangesAdd SystemZ specific changes for dataflow sanitizer on top of following two common code changes See conversation in original pr##162195 Full diff: https://github.com/llvm/llvm-project/pull/168991.diff 11 Files Affected:
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 020e7465548fe..eb2330e35d003 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -914,7 +914,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 ca45d7bd2af7f..2bc695922ef2d 100644
--- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
+++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
@@ -35,7 +35,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..700b2fccf9f6c 100644
--- a/compiler-rt/lib/dfsan/dfsan_allocator.cpp
+++ b/compiler-rt/lib/dfsan/dfsan_allocator.cpp
@@ -44,9 +44,24 @@ struct DFsanMapUnmapCallback {
// duplicated as MappingDesc::ALLOCATOR in dfsan_platform.h.
#if defined(__aarch64__)
const uptr kAllocatorSpace = 0xE00000000000ULL;
+#elif defined(__s390x__)
+const uptr kAllocatorSpace = 0x440000000000ULL;
#else
const uptr kAllocatorSpace = 0x700000000000ULL;
#endif
+#if defined(__s390x__)
+const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
+
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+ static const uptr kSpaceBeg = kAllocatorSpace;
+ static const uptr kSpaceSize = 0x020000000000; // 2T.
+ static const uptr kMetadataSize = sizeof(Metadata);
+ using SizeClassMap = DefaultSizeClassMap;
+ using MapUnmapCallback = DFsanMapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = LocalAddressSpaceView;
+};
+#else
const uptr kMaxAllowedMallocSize = 1ULL << 40;
struct AP64 { // Allocator64 parameters. Deliberately using a short name.
@@ -59,6 +74,7 @@ struct AP64 { // Allocator64 parameters. Deliberately using a short name.
using AddressSpaceView = LocalAddressSpaceView;
};
+#endif
typedef SizeClassAllocator64<AP64> PrimaryAllocator;
typedef CombinedAllocator<PrimaryAllocator> Allocator;
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..7e6a1dafddb50 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, "low memory"},
+ {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, "high memory"}};
+
+# 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..1b4ca6a258bba 100644
--- a/compiler-rt/test/dfsan/lit.cfg.py
+++ b/compiler-rt/test/dfsan/lit.cfg.py
@@ -10,6 +10,8 @@
# Setup default compiler flags used with -fsanitize=dataflow option.
clang_dfsan_cflags = ["-fsanitize=dataflow"] + [config.target_cflags]
+if config.target_arch == "s390x":
+ clang_dfsan_cflags.append("-mbackchain")
clang_dfsan_cxxflags = config.cxx_mode_flags + clang_dfsan_cflags
@@ -25,5 +27,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..cb00339e81ec4 100644
--- a/compiler-rt/test/dfsan/pair.cpp
+++ b/compiler-rt/test/dfsan/pair.cpp
@@ -66,8 +66,10 @@ void test_simple_constructors() {
int *ptr1 = pair1.first;
#ifdef O0
- assert(dfsan_read_label(&i1, sizeof(i1)) == 10);
- assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 10);
+ assert(dfsan_read_label(&i1, sizeof(i1)) == 8 ||
+ dfsan_read_label(&i1, sizeof(i1)) == 10);
+ assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 2 ||
+ dfsan_read_label(&ptr1, sizeof(ptr1)) == 10);
#else
assert(dfsan_read_label(&i1, sizeof(i1)) == 8);
assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 2);
@@ -78,8 +80,10 @@ void test_simple_constructors() {
int *ptr2 = pair2.first;
#ifdef O0
- assert(dfsan_read_label(&i2, sizeof(i2)) == 10);
- assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 10);
+ assert(dfsan_read_label(&i2, sizeof(i2)) == 8 ||
+ dfsan_read_label(&i2, sizeof(i2)) == 10);
+ assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 2 ||
+ dfsan_read_label(&ptr2, sizeof(ptr2)) == 10);
#else
assert(dfsan_read_label(&i2, sizeof(i2)) == 8);
assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 2);
@@ -90,8 +94,10 @@ void test_simple_constructors() {
int *ptr3 = pair3.first;
#ifdef O0
- assert(dfsan_read_label(&i3, sizeof(i3)) == 10);
- assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 10);
+ assert(dfsan_read_label(&i3, sizeof(i3)) == 8 ||
+ dfsan_read_label(&i3, sizeof(i3)) == 10);
+ assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 2 ||
+ dfsan_read_label(&ptr3, sizeof(ptr3)) == 10);
#else
assert(dfsan_read_label(&i3, sizeof(i3)) == 8);
assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 2);
@@ -102,8 +108,10 @@ void test_simple_constructors() {
int *ptr4 = pair4.first;
#ifdef O0
- assert(dfsan_read_label(&i4, sizeof(i4)) == 10);
- assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 10);
+ assert(dfsan_read_label(&i4, sizeof(i4)) == 8 ||
+ dfsan_read_label(&i4, sizeof(i4)) == 10);
+ assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 2 ||
+ dfsan_read_label(&ptr4, sizeof(ptr4)) == 10);
#else
assert(dfsan_read_label(&i4, sizeof(i4)) == 8);
assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 2);
@@ -140,8 +148,10 @@ void test_branches() {
{
std::pair<const char *, uint32_t> r = return_ptr_and_i32(q, res);
#ifdef O0
- assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10);
- assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10);
+ assert(dfsan_read_label(&r.first, sizeof(r.first)) == 2 ||
+ dfsan_read_label(&r.first, sizeof(r.first)) == 10);
+ assert(dfsan_read_label(&r.second, sizeof(r.second)) == 8 ||
+ dfsan_read_label(&r.second, sizeof(r.second)) == 10);
#else
assert(dfsan_read_label(&r.first, sizeof(r.first)) == 2);
assert(dfsan_read_label(&r.second, sizeof(r.second)) == 8);
@@ -151,8 +161,10 @@ void test_branches() {
{
std::pair<const char *, uint64_t> r = return_ptr_and_i64(q, res);
#ifdef O0
- assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10);
- assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10);
+ assert(dfsan_read_label(&r.first, sizeof(r.first)) == 2 ||
+ dfsan_read_label(&r.first, sizeof(r.first)) == 10);
+ assert(dfsan_read_label(&r.second, sizeof(r.second)) == 8 ||
+ dfsan_read_label(&r.second, sizeof(r.second)) == 10);
#else
assert(dfsan_read_label(&r.first, sizeof(r.first)) == 2);
assert(dfsan_read_label(&r.second, sizeof(r.second)) == 8);
diff --git a/compiler-rt/test/dfsan/struct.c b/compiler-rt/test/dfsan/struct.c
index 7ba0016f7beee..48285e022a98a 100644
--- a/compiler-rt/test/dfsan/struct.c
+++ b/compiler-rt/test/dfsan/struct.c
@@ -48,8 +48,8 @@ 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)
- assert(i1_label == (i_label | ptr_label));
- assert(ptr1_label == (i_label | ptr_label));
+ assert(i1_label == i_label || i1_label == (i_label | ptr_label));
+ assert(ptr1_label == ptr_label || ptr1_label == (i_label | ptr_label));
#else
assert(i1_label == i_label);
assert(ptr1_label == ptr_label);
@@ -62,8 +62,8 @@ 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)
- assert(i2_label == (i_label | ptr_label));
- assert(ptr2_label == (i_label | ptr_label));
+ assert(i2_label == i_label || i2_label == (i_label | ptr_label));
+ assert(ptr2_label == ptr_label || ptr2_label == (i_label | ptr_label));
#else
assert(i2_label == i_label);
assert(ptr2_label == ptr_label);
@@ -76,8 +76,8 @@ 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)
- assert(i3_label == (i_label | ptr_label));
- assert(ptr3_label == (i_label | ptr_label));
+ assert(i3_label == i_label || i3_label == (i_label | ptr_label));
+ assert(ptr3_label == ptr_label || ptr3_label == (i_label | ptr_label));
#else
assert(i3_label == i_label);
assert(ptr3_label == ptr_label);
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");
}
|
| #ifdef O0 | ||
| assert(dfsan_read_label(&i1, sizeof(i1)) == 10); | ||
| assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 10); | ||
| assert(dfsan_read_label(&i1, sizeof(i1)) == 8 || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC the test changes are only needed for SystemZ, and therefore make the tests unnecessarily weaker for other platforms. Is it possible to make the alternative options only allowed for SystemZ?
🐧 Linux x64 Test Results
|
Add SystemZ specific changes for dataflow sanitizer on top of following two common code changes
i) Fix Endianness issue #162881
ii) Fix ShadowAddress computation #162864
See conversation in original pr##162195