From 92576b85900eba24ecce49be05388bb04708065b Mon Sep 17 00:00:00 2001 From: "Kenneth Benzie (Benie)" Date: Wed, 31 Jan 2024 12:09:40 +0000 Subject: [PATCH 01/42] [GHA] Bump actions/checkout to v4.1.1 Silence warnings about using outdated version of Node.js due to using actions/checkout@v3.6.0. --- .github/workflows/bandit.yml | 2 +- .github/workflows/cmake.yml | 12 ++++++------ .github/workflows/codeql.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/coverity.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/nightly.yml | 2 +- .github/workflows/prerelease.yml | 2 +- .github/workflows/scorecard.yml | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml index 0687d1f73b..862b278feb 100644 --- a/.github/workflows/bandit.yml +++ b/.github/workflows/bandit.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Clone the git repo - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install pip packages run: pip install -r third_party/requirements.txt diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 717742d973..2507422a90 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -39,7 +39,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install apt packages run: | @@ -125,7 +125,7 @@ jobs: runs-on: 'ubuntu-22.04' steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install pip packages run: pip install -r third_party/requirements.txt @@ -178,7 +178,7 @@ jobs: runs-on: ${{matrix.adapter.name}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install pip packages run: pip install -r third_party/requirements.txt @@ -244,7 +244,7 @@ jobs: runs-on: ${{matrix.adapter.name}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install pip packages run: pip install -r third_party/requirements.txt @@ -310,7 +310,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 with: @@ -361,7 +361,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3bb7c311e4..074f1178cb 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Initialize CodeQL uses: github/codeql-action/init@1500a131381b66de0c52ac28abb13cd79f4b7ecc # v2.22.12 @@ -51,7 +51,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Initialize CodeQL uses: github/codeql-action/init@1500a131381b66de0c52ac28abb13cd79f4b7ecc # v2.22.12 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 9543eeccdd..e1bfd6b1fb 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install apt packages run: | diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 9e46aae20a..ff6fdf6fde 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -33,7 +33,7 @@ jobs: steps: - name: Clone the git repo - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install pip packages run: pip install -r third_party/requirements.txt diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 53734a1d80..66ae042afb 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 with: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a4659e0bc6..3deade6603 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -19,7 +19,7 @@ jobs: runs-on: 'ubuntu-22.04' steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install pip packages run: pip install -r third_party/requirements.txt diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index c7960af331..f1436fc46a 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -15,7 +15,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Create weekly prerelease run: diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 033e796b24..836f3433a3 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -33,7 +33,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: persist-credentials: false From 4a52d274ad9da740df90971182776cb2f26730d1 Mon Sep 17 00:00:00 2001 From: "Kenneth Benzie (Benie)" Date: Wed, 31 Jan 2024 16:12:42 +0000 Subject: [PATCH 02/42] [CL] Handle INTERMEDIATE binary type If an OpenCL driver returns `CL_PROGRAM_BINARY_TYPE_INTERMEDIATE` (defined in the `cl_khr_spir` extension to enable SPIR 1.2 not SPIR-V) when querying `CL_PROGRAM_BINARY_TYPE` we should handle this gracefully. This patch maps the `CL_PROGRAM_BINARY_TYPE_INTERMEDIATE` to `UR_PROGRAM_BINARY_TYPE_NONE`. From the users perspective these are semantically equivalent as they both require compilation before the program can be used to create a kernel. --- source/adapters/opencl/program.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/adapters/opencl/program.cpp b/source/adapters/opencl/program.cpp index f628c8152b..d76cd0b768 100644 --- a/source/adapters/opencl/program.cpp +++ b/source/adapters/opencl/program.cpp @@ -259,6 +259,15 @@ static cl_int mapURProgramBuildInfoToCL(ur_program_build_info_t URPropName) { static ur_program_binary_type_t mapCLBinaryTypeToUR(cl_program_binary_type binaryType) { switch (binaryType) { + default: + // If we don't understand what OpenCL gave us, return NONE. + // TODO: Emit a warning to the user. + [[fallthrough]]; + case CL_PROGRAM_BINARY_TYPE_INTERMEDIATE: + // The INTERMEDIATE binary type is defined by the cl_khr_spir extension + // which we shouldn't encounter but do. Semantically this binary type is + // equivelent to NONE as they both require compilation. + [[fallthrough]]; case CL_PROGRAM_BINARY_TYPE_NONE: return UR_PROGRAM_BINARY_TYPE_NONE; case CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT: @@ -267,8 +276,6 @@ mapCLBinaryTypeToUR(cl_program_binary_type binaryType) { return UR_PROGRAM_BINARY_TYPE_LIBRARY; case CL_PROGRAM_BINARY_TYPE_EXECUTABLE: return UR_PROGRAM_BINARY_TYPE_EXECUTABLE; - default: - return UR_PROGRAM_BINARY_TYPE_FORCE_UINT32; } } From eb63bc1322bb5e57315418ab6c3e1491dc867316 Mon Sep 17 00:00:00 2001 From: "Kenneth Benzie (Benie)" Date: Mon, 29 Jan 2024 11:51:57 +0000 Subject: [PATCH 03/42] [CUDA] Fix sizeof(const char*) usage Replace uses of `sizeof(const char*)` with `std::strlen(const char*)` in CUDA adapter specific kernel tests. --- test/adapters/cuda/kernel_tests.cpp | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/adapters/cuda/kernel_tests.cpp b/test/adapters/cuda/kernel_tests.cpp index c4677af2d0..80ec9146fd 100644 --- a/test/adapters/cuda/kernel_tests.cpp +++ b/test/adapters/cuda/kernel_tests.cpp @@ -74,9 +74,9 @@ const char *threeParamsTwoLocal = "\n\ TEST_P(cudaKernelTest, CreateProgramAndKernel) { uur::raii::Program program = nullptr; - ASSERT_SUCCESS(urProgramCreateWithBinary(context, device, sizeof(ptxSource), - (const uint8_t *)ptxSource, - nullptr, program.ptr())); + ASSERT_SUCCESS(urProgramCreateWithBinary( + context, device, std::strlen(ptxSource), (const uint8_t *)ptxSource, + nullptr, program.ptr())); ASSERT_NE(program, nullptr); ASSERT_SUCCESS(urProgramBuild(context, program, nullptr)); @@ -116,9 +116,9 @@ TEST_P(cudaKernelTest, CreateProgramAndKernelWithMetadata) { ur_program_properties_t programProps{UR_STRUCTURE_TYPE_PROGRAM_PROPERTIES, nullptr, 1, &reqdWorkGroupSizeMDProp}; uur::raii::Program program = nullptr; - ASSERT_SUCCESS(urProgramCreateWithBinary(context, device, sizeof(ptxSource), - (const uint8_t *)ptxSource, - &programProps, program.ptr())); + ASSERT_SUCCESS(urProgramCreateWithBinary( + context, device, std::strlen(ptxSource), (const uint8_t *)ptxSource, + &programProps, program.ptr())); ASSERT_NE(program, nullptr); ASSERT_SUCCESS(urProgramBuild(context, program, nullptr)); @@ -138,9 +138,9 @@ TEST_P(cudaKernelTest, CreateProgramAndKernelWithMetadata) { TEST_P(cudaKernelTest, URKernelArgumentSimple) { uur::raii::Program program = nullptr; - ASSERT_SUCCESS(urProgramCreateWithBinary(context, device, sizeof(ptxSource), - (const uint8_t *)ptxSource, - nullptr, program.ptr())); + ASSERT_SUCCESS(urProgramCreateWithBinary( + context, device, std::strlen(ptxSource), (const uint8_t *)ptxSource, + nullptr, program.ptr())); ASSERT_NE(program, nullptr); ASSERT_SUCCESS(urProgramBuild(context, program, nullptr)); @@ -160,9 +160,9 @@ TEST_P(cudaKernelTest, URKernelArgumentSimple) { TEST_P(cudaKernelTest, URKernelArgumentSetTwice) { uur::raii::Program program = nullptr; - ASSERT_SUCCESS(urProgramCreateWithBinary(context, device, sizeof(ptxSource), - (const uint8_t *)ptxSource, - nullptr, program.ptr())); + ASSERT_SUCCESS(urProgramCreateWithBinary( + context, device, std::strlen(ptxSource), (const uint8_t *)ptxSource, + nullptr, program.ptr())); ASSERT_NE(program, nullptr); ASSERT_SUCCESS(urProgramBuild(context, program, nullptr)); @@ -189,9 +189,9 @@ TEST_P(cudaKernelTest, URKernelArgumentSetTwice) { TEST_P(cudaKernelTest, URKernelDispatch) { uur::raii::Program program = nullptr; - ASSERT_SUCCESS(urProgramCreateWithBinary(context, device, sizeof(ptxSource), - (const uint8_t *)ptxSource, - nullptr, program.ptr())); + ASSERT_SUCCESS(urProgramCreateWithBinary( + context, device, std::strlen(ptxSource), (const uint8_t *)ptxSource, + nullptr, program.ptr())); ASSERT_NE(program, nullptr); ASSERT_SUCCESS(urProgramBuild(context, program, nullptr)); @@ -218,9 +218,9 @@ TEST_P(cudaKernelTest, URKernelDispatch) { TEST_P(cudaKernelTest, URKernelDispatchTwo) { uur::raii::Program program = nullptr; - ASSERT_SUCCESS(urProgramCreateWithBinary(context, device, sizeof(ptxSource), - (const uint8_t *)twoParams, - nullptr, program.ptr())); + ASSERT_SUCCESS(urProgramCreateWithBinary( + context, device, std::strlen(ptxSource), (const uint8_t *)twoParams, + nullptr, program.ptr())); ASSERT_NE(program, nullptr); ASSERT_SUCCESS(urProgramBuild(context, program, nullptr)); From 4652f52aedf4b6815a3c431db3a411b2b789ee53 Mon Sep 17 00:00:00 2001 From: "Kenneth Benzie (Benie)" Date: Thu, 1 Feb 2024 12:18:08 +0000 Subject: [PATCH 04/42] [Docs] Update the Adapter Change Process These changes to the *Adapter Change Process* aim to bring the process up to date with current practice by describing how the *ready to merge* label is being used and also to move the undrafting of *intel/llvm* pull requests earlier in the process to garner approvals from code-reviewers sooner to alleviate a bottleneck in the merge pipeline. --- scripts/core/CONTRIB.rst | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/scripts/core/CONTRIB.rst b/scripts/core/CONTRIB.rst index cf2c8e870b..b622020382 100644 --- a/scripts/core/CONTRIB.rst +++ b/scripts/core/CONTRIB.rst @@ -75,22 +75,42 @@ Adapter Change Process accompanied by a corresponding update in the *intel/llvm* pull request as indicated in step 2, so the testing is always up-to-date. -6. The Unified Runtime maintainers *must* ensure that step 5 has been carried - out and that all pre-merge testing has passed before accepting the +6. Once the *oneapi-src/unified-runtime* pull request has been approved by at + least one member of each relevant code-owner team: + + * Make the *intel/llvm* pull request ready to review (remove draft) in + order to gain approvals from all code-owners to ensure step 8 can + progress quickly when the time comes. + + * Add the *ready to merge* label to the *oneapi-src/unified-runtime* pull + request. + +7. The Unified Runtime maintainers *must* ensure that step 5 has been carried + out and that all pre-merge testing has passed before merging the *oneapi-src/unified-runtime* pull request. -7. Once the *oneapi-src/unified-runtime* pull request is accepted: + * The oldest pull requests with the *ready to merge* label will be + prioritized. + + * Contact the Unified Runtime maintainers if a pull request should be + given a higher priority. + +8. Once the *oneapi-src/unified-runtime* pull request has been merged: * Reverse the change to `UNIFIED_RUNTIME_REPO`_ made in step 2. + * Update the `UNIFIED_RUNTIME_TAG`_ to point at the *oneapi-src/unified-runtime* commit/tag containing the merged adapter changes. + * Update the pull request description, linking to any other *intel/llvm* pull requests who's changes have been merged into *oneapi-src/unified-runtime* but have not yet been merge into *intel/llvm*. - * Mark the *intel/llvm* pull request as ready for review and follow their - review process. + + * A Unified Runtime maintainer may facilitate these steps either by + making suggestions on the *intel/llvm* pull request or by making those + changes directly. .. _oneapi-src/unified-runtime: https://github.com/oneapi-src/unified-runtime From 8e698cdca89c3aefea121855552e71993fb00ceb Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Fri, 2 Feb 2024 04:31:35 -0800 Subject: [PATCH 05/42] wip --- .../layers/sanitizer/asan_interceptor.cpp | 153 ++++++++++++++---- .../layers/sanitizer/asan_interceptor.hpp | 6 +- source/loader/layers/sanitizer/backtrace.hpp | 18 +++ .../layers/sanitizer/linux/backtrace_lin.cpp | 41 +++++ 4 files changed, 189 insertions(+), 29 deletions(-) create mode 100644 source/loader/layers/sanitizer/backtrace.hpp create mode 100644 source/loader/layers/sanitizer/linux/backtrace_lin.cpp diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 88a3b464c2..f870ee723a 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -12,6 +12,9 @@ */ #include "asan_interceptor.hpp" +#include "backtrace.hpp" +#include "device_sanitizer_report.hpp" +#include "ur_api.h" #include "ur_sanitizer_layer.hpp" namespace ur_sanitizer_layer { @@ -24,6 +27,7 @@ constexpr int kUsmDeviceRedzoneMagic = (char)0x81; constexpr int kUsmHostRedzoneMagic = (char)0x82; constexpr int kUsmSharedRedzoneMagic = (char)0x83; constexpr int kMemBufferRedzoneMagic = (char)0x84; +constexpr int kUsmFreedMagic = (char)0x85; constexpr auto kSPIR_AsanShadowMemoryGlobalStart = "__AsanShadowMemoryGlobalStart"; @@ -102,6 +106,76 @@ std::string getKernelName(ur_kernel_handle_t Kernel) { return std::string(KernelNameBuf.data(), KernelNameSize - 1); } +ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, + const void *MemPtr) { + ur_device_handle_t Device; + [[maybe_unused]] auto Result = context.urDdiTable.USM.pfnGetMemAllocInfo( + Context, MemPtr, UR_USM_ALLOC_INFO_DEVICE, sizeof(Device), &Device, + nullptr); + assert(Result == UR_RESULT_SUCCESS); + return Device; +} + +void ReportBadFree(uptr Addr, std::shared_ptr AllocInfo) { + context.logger.always( + "\n====ERROR: DeviceSanitizer: attempting free on address which " + "was not malloc()-ed: {}", + Addr); + + if (!AllocInfo) { // maybe Addr is host allocated memory + context.logger.always("maybe allocated on Host Memory"); + } else { + switch (AllocInfo->Type) { + case USMMemoryType::HOST: + context.logger.always("maybe allocated on Host USM here:"); + break; + case USMMemoryType::SHARE: + context.logger.always("maybe allocated on Shared USM here:"); + break; + case USMMemoryType::DEVICE: + context.logger.always("maybe allocated on Device USM here:"); + break; + default: + context.logger.always("maybe allocated on Unknown Memory here:"); + } + for (unsigned i = 0; i < AllocInfo->AllocStack.size(); ++i) { + auto Line = AllocInfo->AllocStack[i]; + context.logger.always(" #{} {}", i, Line); + } + } + + exit(1); +} + +} + +void ReportDoubleFree(uptr Addr, std::vector Stack, std::shared_ptr AllocInfo) { + +} + +void ReportUseAfterFree(uptr Addr, std::shared_ptr AllocInfo) {} + +void ReportGenericError(DeviceSanitizerReport &Report, + ur_kernel_handle_t Kernel) { + const char *File = Report.File[0] ? Report.File : ""; + const char *Func = Report.Func[0] ? Report.Func : ""; + auto KernelName = getKernelName(Kernel); + + context.logger.always("\n====ERROR: DeviceSanitizer: {} on {}", + DeviceSanitizerFormat(Report.ErrorType), + DeviceSanitizerFormat(Report.MemoryType)); + context.logger.always( + "{} of size {} at kernel <{}> LID({}, {}, {}) GID({}, " + "{}, {})", + Report.IsWrite ? "WRITE" : "READ", Report.AccessSize, + KernelName.c_str(), Report.LID0, Report.LID1, Report.LID2, Report.GID0, + Report.GID1, Report.GID2); + context.logger.always(" #0 {} {}:{}", Func, File, Report.Line); + if (!Report.IsRecover) { + exit(1); + } +} + } // namespace SanitizerInterceptor::SanitizerInterceptor() @@ -173,8 +247,14 @@ ur_result_t SanitizerInterceptor::allocateMemory( *ResultPtr = reinterpret_cast(UserBegin); - auto AllocInfo = std::make_shared( - USMAllocInfo{AllocBegin, UserBegin, UserEnd, NeededSize, Type}); + auto AllocInfo = + std::make_shared(USMAllocInfo{AllocBegin, + UserBegin, + UserEnd, + NeededSize, + Type, + GetCurrentBacktrace(), + {}}); // For updating shadow memory if (DeviceInfo) { // device/shared USM @@ -210,27 +290,53 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, auto Addr = reinterpret_cast(Ptr); // Find the last element is not greater than key - auto AllocInfoIt = ContextInfo->AllocatedUSMMap.upper_bound((uptr)Addr); + auto AllocInfoIt = ContextInfo->AllocatedUSMMap.upper_bound(Addr); if (AllocInfoIt == ContextInfo->AllocatedUSMMap.begin()) { - context.logger.error( - "Can't find release pointer({}) in AllocatedAddressesMap", Ptr); + ReportBadFree(Addr, nullptr); return UR_RESULT_ERROR_INVALID_ARGUMENT; } --AllocInfoIt; auto &AllocInfo = AllocInfoIt->second; - context.logger.debug("USMAllocInfo(AllocBegin={}, UserBegin={})", AllocInfo->AllocBegin, AllocInfo->UserBegin); + auto AllocType = AllocInfo->Type; + + if (AllocType == USMMemoryType::RELEASED) { + ReportDoubleFree(Addr, AllocInfo); + return UR_RESULT_ERROR_INVALID_ARGUMENT; + } + if (Addr != AllocInfo->UserBegin) { - context.logger.error("Releasing pointer({}) is not match to {}", Ptr, - AllocInfo->UserBegin); + ReportBadFree(Addr, AllocInfo); return UR_RESULT_ERROR_INVALID_ARGUMENT; } - // TODO: Update shadow memory - return context.urDdiTable.USM.pfnFree(Context, - (void *)AllocInfo->AllocBegin); + AllocInfo->Type = USMMemoryType::RELEASED; + AllocInfo->ReleaseStack = GetCurrentBacktrace(); + + auto Device = + getUSMAllocDevice(Context, (const void *)AllocInfo->AllocBegin); + + // auto Res = + // context.urDdiTable.USM.pfnFree(Context, (void *)AllocInfo->AllocBegin); + // if (Res != UR_RESULT_SUCCESS) { + // return Res; + // } + + if (AllocType == USMMemoryType::HOST) { + for (auto &pair : ContextInfo->DeviceMap) { + auto DeviceInfo = pair.second; + std::scoped_lock Guard(DeviceInfo->Mutex); + DeviceInfo->AllocInfos.emplace_back(AllocInfo); + } + } else { + auto DeviceInfo = ContextInfo->getDeviceInfo(Device); + std::scoped_lock Guard(DeviceInfo->Mutex); + DeviceInfo->AllocInfos.emplace_back(AllocInfo); + } + + return UR_RESULT_SUCCESS; } ur_result_t SanitizerInterceptor::preLaunchKernel(ur_kernel_handle_t Kernel, @@ -276,23 +382,7 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, if (!AH->Flag) { return; } - - const char *File = AH->File[0] ? AH->File : ""; - const char *Func = AH->Func[0] ? AH->Func : ""; - auto KernelName = getKernelName(Kernel); - - context.logger.always("\n====ERROR: DeviceSanitizer: {} on {}", - DeviceSanitizerFormat(AH->ErrorType), - DeviceSanitizerFormat(AH->MemoryType)); - context.logger.always( - "{} of size {} at kernel <{}> LID({}, {}, {}) GID({}, " - "{}, {})", - AH->IsWrite ? "WRITE" : "READ", AH->AccessSize, KernelName.c_str(), - AH->LID0, AH->LID1, AH->LID2, AH->GID0, AH->GID1, AH->GID2); - context.logger.always(" #0 {} {}:{}", Func, File, AH->Line); - if (!AH->IsRecover) { - exit(1); - } + ReportGenericError(*AH, Kernel); } } @@ -479,6 +569,13 @@ ur_result_t SanitizerInterceptor::enqueueAllocInfo( ur_context_handle_t Context, ur_device_handle_t Device, ur_queue_handle_t Queue, std::shared_ptr &AllocInfo, ur_event_handle_t &LastEvent) { + if (AllocInfo->Type == USMMemoryType::RELEASED) { + UR_CALL(enqueueMemSetShadow(Context, Device, Queue, + AllocInfo->AllocBegin, AllocInfo->AllocSize, + kUsmFreedMagic, LastEvent, &LastEvent)); + return UR_RESULT_SUCCESS; + } + // Init zero UR_CALL(enqueueMemSetShadow(Context, Device, Queue, AllocInfo->AllocBegin, AllocInfo->AllocSize, 0, LastEvent, diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 0753b53d63..65131477fc 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -12,6 +12,7 @@ #pragma once +#include "backtrace.hpp" #include "common.hpp" #include "device_sanitizer_report.hpp" @@ -22,7 +23,7 @@ namespace ur_sanitizer_layer { -enum USMMemoryType { DEVICE, SHARE, HOST, MEM_BUFFER }; +enum USMMemoryType { DEVICE, SHARE, HOST, MEM_BUFFER, RELEASED }; struct USMAllocInfo { uptr AllocBegin; @@ -30,6 +31,9 @@ struct USMAllocInfo { uptr UserEnd; size_t AllocSize; USMMemoryType Type; + + std::vector AllocStack; + std::vector ReleaseStack; }; enum class DeviceType { UNKNOWN, CPU, GPU_PVC, GPU_DG2 }; diff --git a/source/loader/layers/sanitizer/backtrace.hpp b/source/loader/layers/sanitizer/backtrace.hpp new file mode 100644 index 0000000000..0a50dc3071 --- /dev/null +++ b/source/loader/layers/sanitizer/backtrace.hpp @@ -0,0 +1,18 @@ +// Copyright (C) 2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once + +#include +#include + +#define MAX_BACKTRACE_FRAMES 64 + +namespace ur_sanitizer_layer { + +using BacktraceLine = std::string; +std::vector GetCurrentBacktrace(); + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/linux/backtrace_lin.cpp b/source/loader/layers/sanitizer/linux/backtrace_lin.cpp new file mode 100644 index 0000000000..a6d8dccab2 --- /dev/null +++ b/source/loader/layers/sanitizer/linux/backtrace_lin.cpp @@ -0,0 +1,41 @@ +/* + * + * Copyright (C) 2023 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + */ +#include "backtrace.hpp" + +#include +#include + +namespace ur_sanitizer_layer { + +std::vector getCurrentBacktrace() { + void *backtraceFrames[MAX_BACKTRACE_FRAMES]; + int frameCount = backtrace(backtraceFrames, MAX_BACKTRACE_FRAMES); + char **backtraceStr = backtrace_symbols(backtraceFrames, frameCount); + + if (backtraceStr == nullptr) { + return std::vector(1, "Failed to acquire a backtrace"); + } + + std::vector backtrace; + try { + for (int i = 0; i < frameCount; i++) { + backtrace.emplace_back(backtraceStr[i]); + } + } catch (std::bad_alloc &) { + free(backtraceStr); + return std::vector(1, "Failed to acquire a backtrace"); + } + + free(backtraceStr); + + return backtrace; +} + +} // namespace ur_sanitizer_layer From f23e2c1dcbbb4c77f90e8e2481f1c04c6e67fd83 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sat, 3 Feb 2024 22:11:25 -0800 Subject: [PATCH 06/42] bad free --- source/loader/CMakeLists.txt | 5 +- .../layers/sanitizer/asan_interceptor.cpp | 104 ++++++++++-------- .../layers/sanitizer/asan_interceptor.hpp | 12 +- source/loader/layers/sanitizer/backtrace.hpp | 18 --- .../layers/sanitizer/linux/backtrace_lin.cpp | 21 ++-- source/loader/layers/sanitizer/stacktrace.cpp | 32 ++++++ source/loader/layers/sanitizer/stacktrace.hpp | 32 ++++++ source/loader/layers/sanitizer/ur_sanddi.cpp | 6 +- 8 files changed, 144 insertions(+), 86 deletions(-) delete mode 100644 source/loader/layers/sanitizer/backtrace.hpp create mode 100644 source/loader/layers/sanitizer/stacktrace.cpp create mode 100644 source/loader/layers/sanitizer/stacktrace.hpp diff --git a/source/loader/CMakeLists.txt b/source/loader/CMakeLists.txt index 474fa6c79b..38495de4ab 100644 --- a/source/loader/CMakeLists.txt +++ b/source/loader/CMakeLists.txt @@ -110,14 +110,17 @@ if(UR_ENABLE_SANITIZER) ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_interceptor.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/common.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/device_sanitizer_report.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/stacktrace.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/stacktrace.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanddi.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanddi.cpp ) target_sources(ur_loader PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/san_utils.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/backtrace_lin.cpp ) target_include_directories(ur_loader PRIVATE diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index f870ee723a..6bb84cd10b 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -12,8 +12,8 @@ */ #include "asan_interceptor.hpp" -#include "backtrace.hpp" #include "device_sanitizer_report.hpp" +#include "stacktrace.hpp" #include "ur_api.h" #include "ur_sanitizer_layer.hpp" @@ -116,41 +116,56 @@ ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, return Device; } -void ReportBadFree(uptr Addr, std::shared_ptr AllocInfo) { +const char *getFormatString(MemoryType MemoryType) { + switch (MemoryType) { + case MemoryType::DEVICE_USM: + return "USM Device Memory"; + case MemoryType::HOST_USM: + return "USM Host Memory"; + case MemoryType::SHARED_USM: + return "USM Shared Memory"; + case MemoryType::MEM_BUFFER: + return "Memory Buffer"; + default: + return "Unknown Memory"; + } +} + +void ReportBadFree(uptr Addr, StackTrace stack, + std::shared_ptr AllocInfo) { + // attempting free on address which was not malloc()-ed: 0x511000023184 in thread T0 context.logger.always( "\n====ERROR: DeviceSanitizer: attempting free on address which " - "was not malloc()-ed: {}", - Addr); + "was not malloc()-ed: {} in thread T0", + (void *)Addr); + stack.Print(); if (!AllocInfo) { // maybe Addr is host allocated memory - context.logger.always("maybe allocated on Host Memory"); - } else { - switch (AllocInfo->Type) { - case USMMemoryType::HOST: - context.logger.always("maybe allocated on Host USM here:"); - break; - case USMMemoryType::SHARE: - context.logger.always("maybe allocated on Shared USM here:"); - break; - case USMMemoryType::DEVICE: - context.logger.always("maybe allocated on Device USM here:"); - break; - default: - context.logger.always("maybe allocated on Unknown Memory here:"); - } - for (unsigned i = 0; i < AllocInfo->AllocStack.size(); ++i) { - auto Line = AllocInfo->AllocStack[i]; - context.logger.always(" #{} {}", i, Line); - } + context.logger.always("{} is maybe allocated on Host Memory", + (void *)Addr); + exit(1); } - exit(1); -} + assert(AllocInfo->Type != MemoryType::RELEASED); -} + // 0x511000023184 is located 4 bytes inside of 256-byte region [0x511000023180,0x511000023280) + // allocated by thread T0 here: + context.logger.always("{} is located inside of {} region [{}, {}]", + (void *)Addr, getFormatString(AllocInfo->Type), + (void *)AllocInfo->UserBegin, + (void *)AllocInfo->UserEnd); + context.logger.always("allocated by thread T0 here:"); + AllocInfo->AllocStack.Print(); -void ReportDoubleFree(uptr Addr, std::vector Stack, std::shared_ptr AllocInfo) { + exit(1); +} +void ReportDoubleFree(uptr Addr, StackTrace Stack, + std::shared_ptr AllocInfo) { + context.logger.always("\n====ERROR: DeviceSanitizer: double-free on {}", + (void *)Addr); + Stack.Print(); + exit(1); } void ReportUseAfterFree(uptr Addr, std::shared_ptr AllocInfo) {} @@ -198,7 +213,7 @@ SanitizerInterceptor::~SanitizerInterceptor() { ur_result_t SanitizerInterceptor::allocateMemory( ur_context_handle_t Context, ur_device_handle_t Device, const ur_usm_desc_t *Properties, ur_usm_pool_handle_t Pool, size_t Size, - void **ResultPtr, USMMemoryType Type) { + void **ResultPtr, MemoryType Type) { auto Alignment = Properties->align; assert(Alignment == 0 || IsPowerOfTwo(Alignment)); @@ -221,13 +236,13 @@ ur_result_t SanitizerInterceptor::allocateMemory( void *Allocated = nullptr; - if (Type == USMMemoryType::DEVICE) { + if (Type == MemoryType::DEVICE_USM) { UR_CALL(context.urDdiTable.USM.pfnDeviceAlloc( Context, Device, Properties, Pool, NeededSize, &Allocated)); - } else if (Type == USMMemoryType::HOST) { + } else if (Type == MemoryType::HOST_USM) { UR_CALL(context.urDdiTable.USM.pfnHostAlloc(Context, Properties, Pool, NeededSize, &Allocated)); - } else if (Type == USMMemoryType::SHARE) { + } else if (Type == MemoryType::SHARED_USM) { UR_CALL(context.urDdiTable.USM.pfnSharedAlloc( Context, Device, Properties, Pool, NeededSize, &Allocated)); } else { @@ -292,27 +307,28 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, // Find the last element is not greater than key auto AllocInfoIt = ContextInfo->AllocatedUSMMap.upper_bound(Addr); if (AllocInfoIt == ContextInfo->AllocatedUSMMap.begin()) { - ReportBadFree(Addr, nullptr); + ReportBadFree(Addr, GetCurrentBacktrace(), nullptr); return UR_RESULT_ERROR_INVALID_ARGUMENT; } --AllocInfoIt; auto &AllocInfo = AllocInfoIt->second; - context.logger.debug("USMAllocInfo(AllocBegin={}, UserBegin={})", - AllocInfo->AllocBegin, AllocInfo->UserBegin); + context.logger.debug("AllocInfo(AllocBegin={}, UserBegin={})", + (void *)AllocInfo->AllocBegin, + (void *)AllocInfo->UserBegin); auto AllocType = AllocInfo->Type; - if (AllocType == USMMemoryType::RELEASED) { - ReportDoubleFree(Addr, AllocInfo); + if (AllocType == MemoryType::RELEASED) { + ReportDoubleFree(Addr, GetCurrentBacktrace(), AllocInfo); return UR_RESULT_ERROR_INVALID_ARGUMENT; } if (Addr != AllocInfo->UserBegin) { - ReportBadFree(Addr, AllocInfo); + ReportBadFree(Addr, GetCurrentBacktrace(), AllocInfo); return UR_RESULT_ERROR_INVALID_ARGUMENT; } - AllocInfo->Type = USMMemoryType::RELEASED; + AllocInfo->Type = MemoryType::RELEASED; AllocInfo->ReleaseStack = GetCurrentBacktrace(); auto Device = @@ -324,7 +340,7 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, // return Res; // } - if (AllocType == USMMemoryType::HOST) { + if (AllocType == MemoryType::HOST_USM) { for (auto &pair : ContextInfo->DeviceMap) { auto DeviceInfo = pair.second; std::scoped_lock Guard(DeviceInfo->Mutex); @@ -569,7 +585,7 @@ ur_result_t SanitizerInterceptor::enqueueAllocInfo( ur_context_handle_t Context, ur_device_handle_t Device, ur_queue_handle_t Queue, std::shared_ptr &AllocInfo, ur_event_handle_t &LastEvent) { - if (AllocInfo->Type == USMMemoryType::RELEASED) { + if (AllocInfo->Type == MemoryType::RELEASED) { UR_CALL(enqueueMemSetShadow(Context, Device, Queue, AllocInfo->AllocBegin, AllocInfo->AllocSize, kUsmFreedMagic, LastEvent, &LastEvent)); @@ -595,16 +611,16 @@ ur_result_t SanitizerInterceptor::enqueueAllocInfo( int ShadowByte; switch (AllocInfo->Type) { - case USMMemoryType::HOST: + case MemoryType::HOST_USM: ShadowByte = kUsmHostRedzoneMagic; break; - case USMMemoryType::DEVICE: + case MemoryType::DEVICE_USM: ShadowByte = kUsmDeviceRedzoneMagic; break; - case USMMemoryType::SHARE: + case MemoryType::SHARED_USM: ShadowByte = kUsmSharedRedzoneMagic; break; - case USMMemoryType::MEM_BUFFER: + case MemoryType::MEM_BUFFER: ShadowByte = kMemBufferRedzoneMagic; break; default: diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 65131477fc..8902c422ea 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -12,9 +12,9 @@ #pragma once -#include "backtrace.hpp" #include "common.hpp" #include "device_sanitizer_report.hpp" +#include "stacktrace.hpp" #include #include @@ -23,17 +23,17 @@ namespace ur_sanitizer_layer { -enum USMMemoryType { DEVICE, SHARE, HOST, MEM_BUFFER, RELEASED }; +enum MemoryType { DEVICE_USM, SHARED_USM, HOST_USM, MEM_BUFFER, RELEASED }; struct USMAllocInfo { uptr AllocBegin; uptr UserBegin; uptr UserEnd; size_t AllocSize; - USMMemoryType Type; + MemoryType Type; - std::vector AllocStack; - std::vector ReleaseStack; + StackTrace AllocStack; + StackTrace ReleaseStack; }; enum class DeviceType { UNKNOWN, CPU, GPU_PVC, GPU_DG2 }; @@ -109,7 +109,7 @@ class SanitizerInterceptor { ur_device_handle_t Device, const ur_usm_desc_t *Properties, ur_usm_pool_handle_t Pool, size_t Size, - void **ResultPtr, USMMemoryType Type); + void **ResultPtr, MemoryType Type); ur_result_t releaseMemory(ur_context_handle_t Context, void *Ptr); ur_result_t preLaunchKernel(ur_kernel_handle_t Kernel, diff --git a/source/loader/layers/sanitizer/backtrace.hpp b/source/loader/layers/sanitizer/backtrace.hpp deleted file mode 100644 index 0a50dc3071..0000000000 --- a/source/loader/layers/sanitizer/backtrace.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See LICENSE.TXT -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#pragma once - -#include -#include - -#define MAX_BACKTRACE_FRAMES 64 - -namespace ur_sanitizer_layer { - -using BacktraceLine = std::string; -std::vector GetCurrentBacktrace(); - -} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/linux/backtrace_lin.cpp b/source/loader/layers/sanitizer/linux/backtrace_lin.cpp index a6d8dccab2..6748eed667 100644 --- a/source/loader/layers/sanitizer/linux/backtrace_lin.cpp +++ b/source/loader/layers/sanitizer/linux/backtrace_lin.cpp @@ -7,35 +7,28 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception * */ -#include "backtrace.hpp" +#include "stacktrace.hpp" #include -#include namespace ur_sanitizer_layer { -std::vector getCurrentBacktrace() { +StackTrace GetCurrentBacktrace() { void *backtraceFrames[MAX_BACKTRACE_FRAMES]; int frameCount = backtrace(backtraceFrames, MAX_BACKTRACE_FRAMES); char **backtraceStr = backtrace_symbols(backtraceFrames, frameCount); if (backtraceStr == nullptr) { - return std::vector(1, "Failed to acquire a backtrace"); + return StackTrace(); } - std::vector backtrace; - try { - for (int i = 0; i < frameCount; i++) { - backtrace.emplace_back(backtraceStr[i]); - } - } catch (std::bad_alloc &) { - free(backtraceStr); - return std::vector(1, "Failed to acquire a backtrace"); + StackTrace stack; + for (int i = 0; i < frameCount; i++) { + stack.stack.emplace_back(backtraceStr[i]); } - free(backtraceStr); - return backtrace; + return stack; } } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/stacktrace.cpp b/source/loader/layers/sanitizer/stacktrace.cpp new file mode 100644 index 0000000000..9b982e2e98 --- /dev/null +++ b/source/loader/layers/sanitizer/stacktrace.cpp @@ -0,0 +1,32 @@ +/* + * + * Copyright (C) 2023 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file stacktrace.cpp + * + */ + +#pragma once + +#include "stacktrace.hpp" +#include "ur_sanitizer_layer.hpp" + +namespace ur_sanitizer_layer { + +#define MAX_BACKTRACE_FRAMES 64 + +void StackTrace::Print() const { + if (!stack.size()) { + context.logger.always(" failed to acquire backtrace"); + } + for (unsigned i = 0; i < stack.size(); ++i) { + context.logger.always(" #{} {}", i, stack[i]); + } + context.logger.always(""); +} + +} // namespace ur_sanitizer_layer \ No newline at end of file diff --git a/source/loader/layers/sanitizer/stacktrace.hpp b/source/loader/layers/sanitizer/stacktrace.hpp new file mode 100644 index 0000000000..897b9b1001 --- /dev/null +++ b/source/loader/layers/sanitizer/stacktrace.hpp @@ -0,0 +1,32 @@ +/* + * + * Copyright (C) 2023 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file stacktrace.hpp + * + */ + +#pragma once + +#include +#include + +namespace ur_sanitizer_layer { + +#define MAX_BACKTRACE_FRAMES 64 + +using BacktraceLine = std::string; + +struct StackTrace { + std::vector stack; + + void Print() const; +}; + +StackTrace GetCurrentBacktrace(); + +} // namespace ur_sanitizer_layer \ No newline at end of file diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index 7bd49e4ff0..13da364ee6 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -36,7 +36,7 @@ __urdlllocal ur_result_t UR_APICALL urUSMHostAlloc( context.logger.debug("==== urUSMHostAlloc"); return context.interceptor->allocateMemory( - hContext, nullptr, pUSMDesc, pool, size, ppMem, USMMemoryType::HOST); + hContext, nullptr, pUSMDesc, pool, size, ppMem, MemoryType::HOST_USM); } /////////////////////////////////////////////////////////////////////////////// @@ -61,7 +61,7 @@ __urdlllocal ur_result_t UR_APICALL urUSMDeviceAlloc( context.logger.debug("==== urUSMDeviceAlloc"); return context.interceptor->allocateMemory( - hContext, hDevice, pUSMDesc, pool, size, ppMem, USMMemoryType::DEVICE); + hContext, hDevice, pUSMDesc, pool, size, ppMem, MemoryType::DEVICE_USM); } /////////////////////////////////////////////////////////////////////////////// @@ -86,7 +86,7 @@ __urdlllocal ur_result_t UR_APICALL urUSMSharedAlloc( context.logger.debug("==== urUSMSharedAlloc"); return context.interceptor->allocateMemory( - hContext, hDevice, pUSMDesc, pool, size, ppMem, USMMemoryType::SHARE); + hContext, hDevice, pUSMDesc, pool, size, ppMem, MemoryType::SHARED_USM); } /////////////////////////////////////////////////////////////////////////////// From 0b6afb8f0f77456351132d639c74306aee5ae76c Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 6 Feb 2024 17:19:18 -0800 Subject: [PATCH 07/42] initial implementation --- source/loader/CMakeLists.txt | 4 +- .../layers/sanitizer/asan_interceptor.cpp | 171 +++++++++++++----- .../layers/sanitizer/asan_interceptor.hpp | 51 ++++-- source/loader/layers/sanitizer/common.hpp | 14 +- .../sanitizer/device_sanitizer_report.hpp | 1 + .../{backtrace_lin.cpp => backtrace.cpp} | 19 +- .../sanitizer/linux/symbolizer_llvm.cpp | 64 +++++++ source/loader/layers/sanitizer/stacktrace.cpp | 35 +++- source/loader/layers/sanitizer/stacktrace.hpp | 8 +- .../layers/sanitizer/symbolizer_llvm.hpp | 30 +++ 10 files changed, 317 insertions(+), 80 deletions(-) rename source/loader/layers/sanitizer/linux/{backtrace_lin.cpp => backtrace.cpp} (57%) create mode 100644 source/loader/layers/sanitizer/linux/symbolizer_llvm.cpp create mode 100644 source/loader/layers/sanitizer/symbolizer_llvm.hpp diff --git a/source/loader/CMakeLists.txt b/source/loader/CMakeLists.txt index 38495de4ab..7a77f7c63e 100644 --- a/source/loader/CMakeLists.txt +++ b/source/loader/CMakeLists.txt @@ -115,12 +115,14 @@ if(UR_ENABLE_SANITIZER) ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanddi.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/symbolizer_llvm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/symbolizer_llvm.hpp ) target_sources(ur_loader PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/san_utils.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/backtrace_lin.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/backtrace.cpp ) target_include_directories(ur_loader PRIVATE diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 6bb84cd10b..96d956d7c3 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -27,7 +27,11 @@ constexpr int kUsmDeviceRedzoneMagic = (char)0x81; constexpr int kUsmHostRedzoneMagic = (char)0x82; constexpr int kUsmSharedRedzoneMagic = (char)0x83; constexpr int kMemBufferRedzoneMagic = (char)0x84; -constexpr int kUsmFreedMagic = (char)0x85; + +const int kUsmDeviceDeallocatedMagic = (char)0x91; +const int kUsmHostDeallocatedMagic = (char)0x92; +const int kUsmSharedDeallocatedMagic = (char)0x93; +const int kMemBufferDeallocatedMagic = (char)0x93; constexpr auto kSPIR_AsanShadowMemoryGlobalStart = "__AsanShadowMemoryGlobalStart"; @@ -133,7 +137,6 @@ const char *getFormatString(MemoryType MemoryType) { void ReportBadFree(uptr Addr, StackTrace stack, std::shared_ptr AllocInfo) { - // attempting free on address which was not malloc()-ed: 0x511000023184 in thread T0 context.logger.always( "\n====ERROR: DeviceSanitizer: attempting free on address which " "was not malloc()-ed: {} in thread T0", @@ -146,10 +149,8 @@ void ReportBadFree(uptr Addr, StackTrace stack, exit(1); } - assert(AllocInfo->Type != MemoryType::RELEASED); + assert(!AllocInfo->IsReleased && "Chunk must be not released"); - // 0x511000023184 is located 4 bytes inside of 256-byte region [0x511000023180,0x511000023280) - // allocated by thread T0 here: context.logger.always("{} is located inside of {} region [{}, {}]", (void *)Addr, getFormatString(AllocInfo->Type), (void *)AllocInfo->UserBegin, @@ -165,13 +166,14 @@ void ReportDoubleFree(uptr Addr, StackTrace Stack, context.logger.always("\n====ERROR: DeviceSanitizer: double-free on {}", (void *)Addr); Stack.Print(); + AllocInfo->AllocStack.Print(); + AllocInfo->ReleaseStack.Print(); exit(1); } -void ReportUseAfterFree(uptr Addr, std::shared_ptr AllocInfo) {} - void ReportGenericError(DeviceSanitizerReport &Report, - ur_kernel_handle_t Kernel) { + ur_kernel_handle_t Kernel, ur_context_handle_t Context, + ur_device_handle_t Device) { const char *File = Report.File[0] ? Report.File : ""; const char *Func = Report.Func[0] ? Report.Func : ""; auto KernelName = getKernelName(Kernel); @@ -185,10 +187,31 @@ void ReportGenericError(DeviceSanitizerReport &Report, Report.IsWrite ? "WRITE" : "READ", Report.AccessSize, KernelName.c_str(), Report.LID0, Report.LID1, Report.LID2, Report.GID0, Report.GID1, Report.GID2); - context.logger.always(" #0 {} {}:{}", Func, File, Report.Line); - if (!Report.IsRecover) { - exit(1); + context.logger.always(" #0 {} {}:{}\n", Func, File, Report.Line); + + if (Report.ErrorType == DeviceSanitizerErrorType::USE_AFTER_FREE) { + auto AllocInfos = context.interceptor->findAllocInfoByAddress( + Report.Addr, Context, Device); + if (!AllocInfos.size()) { + context.logger.always("can't find which chunck {} is allocated", + (void *)Report.Addr); + } + for (auto &AllocInfo : AllocInfos) { + if (!AllocInfo->IsReleased) { + continue; + } + context.logger.always( + "{} is located inside of {} region [{}, {}]", + (void *)Report.Addr, getFormatString(AllocInfo->Type), + (void *)AllocInfo->UserBegin, (void *)AllocInfo->UserEnd); + context.logger.always("allocated by thread T0 here:"); + AllocInfo->AllocStack.Print(); + context.logger.always("released by thread T0 here:"); + AllocInfo->ReleaseStack.Print(); + } } + + exit(1); } } // namespace @@ -268,6 +291,9 @@ ur_result_t SanitizerInterceptor::allocateMemory( UserEnd, NeededSize, Type, + false, + Context, + Device, GetCurrentBacktrace(), {}}); @@ -285,8 +311,8 @@ ur_result_t SanitizerInterceptor::allocateMemory( // For memory release { - std::scoped_lock Guard(ContextInfo->Mutex); - ContextInfo->AllocatedUSMMap[AllocBegin] = std::move(AllocInfo); + std::scoped_lock Guard(m_AllocationsMapMutex); + m_AllocationsMap.emplace(std::move(AllocInfo)); } context.logger.info( @@ -304,52 +330,51 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, std::shared_lock Guard(ContextInfo->Mutex); auto Addr = reinterpret_cast(Ptr); - // Find the last element is not greater than key - auto AllocInfoIt = ContextInfo->AllocatedUSMMap.upper_bound(Addr); - if (AllocInfoIt == ContextInfo->AllocatedUSMMap.begin()) { + auto AllocInfos = findAllocInfoByAddress(Addr, Context, nullptr); + + if (!AllocInfos.size()) { ReportBadFree(Addr, GetCurrentBacktrace(), nullptr); return UR_RESULT_ERROR_INVALID_ARGUMENT; } - --AllocInfoIt; - auto &AllocInfo = AllocInfoIt->second; - context.logger.debug("AllocInfo(AllocBegin={}, UserBegin={})", - (void *)AllocInfo->AllocBegin, - (void *)AllocInfo->UserBegin); - auto AllocType = AllocInfo->Type; + for (auto AllocInfo : AllocInfos) { + context.logger.debug("AllocInfo(AllocBegin={}, UserBegin={})", + (void *)AllocInfo->AllocBegin, + (void *)AllocInfo->UserBegin); - if (AllocType == MemoryType::RELEASED) { - ReportDoubleFree(Addr, GetCurrentBacktrace(), AllocInfo); - return UR_RESULT_ERROR_INVALID_ARGUMENT; - } + if (AllocInfo->IsReleased) { + ReportDoubleFree(Addr, GetCurrentBacktrace(), AllocInfo); + return UR_RESULT_ERROR_INVALID_ARGUMENT; + } - if (Addr != AllocInfo->UserBegin) { - ReportBadFree(Addr, GetCurrentBacktrace(), AllocInfo); - return UR_RESULT_ERROR_INVALID_ARGUMENT; - } + if (Addr != AllocInfo->UserBegin) { + ReportBadFree(Addr, GetCurrentBacktrace(), AllocInfo); + return UR_RESULT_ERROR_INVALID_ARGUMENT; + } - AllocInfo->Type = MemoryType::RELEASED; - AllocInfo->ReleaseStack = GetCurrentBacktrace(); + AllocInfo->IsReleased = true; + AllocInfo->ReleaseStack = GetCurrentBacktrace(); - auto Device = - getUSMAllocDevice(Context, (const void *)AllocInfo->AllocBegin); + auto Device = + getUSMAllocDevice(Context, (const void *)AllocInfo->AllocBegin); - // auto Res = - // context.urDdiTable.USM.pfnFree(Context, (void *)AllocInfo->AllocBegin); - // if (Res != UR_RESULT_SUCCESS) { - // return Res; - // } + // auto Res = + // context.urDdiTable.USM.pfnFree(Context, (void *)AllocInfo->AllocBegin); + // if (Res != UR_RESULT_SUCCESS) { + // return Res; + // } - if (AllocType == MemoryType::HOST_USM) { - for (auto &pair : ContextInfo->DeviceMap) { - auto DeviceInfo = pair.second; + if (AllocInfo->Type == MemoryType::HOST_USM) { + for (auto &pair : ContextInfo->DeviceMap) { + auto DeviceInfo = pair.second; + std::scoped_lock Guard(DeviceInfo->Mutex); + DeviceInfo->AllocInfos.emplace_back(AllocInfo); + } + } else { + auto DeviceInfo = ContextInfo->getDeviceInfo(Device); std::scoped_lock Guard(DeviceInfo->Mutex); DeviceInfo->AllocInfos.emplace_back(AllocInfo); } - } else { - auto DeviceInfo = ContextInfo->getDeviceInfo(Device); - std::scoped_lock Guard(DeviceInfo->Mutex); - DeviceInfo->AllocInfos.emplace_back(AllocInfo); } return UR_RESULT_SUCCESS; @@ -398,7 +423,7 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, if (!AH->Flag) { return; } - ReportGenericError(*AH, Kernel); + ReportGenericError(*AH, Kernel, getContext(Queue), getDevice(Queue)); } } @@ -585,10 +610,28 @@ ur_result_t SanitizerInterceptor::enqueueAllocInfo( ur_context_handle_t Context, ur_device_handle_t Device, ur_queue_handle_t Queue, std::shared_ptr &AllocInfo, ur_event_handle_t &LastEvent) { - if (AllocInfo->Type == MemoryType::RELEASED) { + if (AllocInfo->IsReleased) { + int ShadowByte; + switch (AllocInfo->Type) { + case MemoryType::HOST_USM: + ShadowByte = kUsmHostDeallocatedMagic; + break; + case MemoryType::DEVICE_USM: + ShadowByte = kUsmDeviceDeallocatedMagic; + break; + case MemoryType::SHARED_USM: + ShadowByte = kUsmSharedDeallocatedMagic; + break; + case MemoryType::MEM_BUFFER: + ShadowByte = kMemBufferDeallocatedMagic; + break; + default: + ShadowByte = 0xff; + assert(false && "Unknow AllocInfo Type"); + } UR_CALL(enqueueMemSetShadow(Context, Device, Queue, AllocInfo->AllocBegin, AllocInfo->AllocSize, - kUsmFreedMagic, LastEvent, &LastEvent)); + ShadowByte, LastEvent, &LastEvent)); return UR_RESULT_SUCCESS; } @@ -846,6 +889,36 @@ ur_result_t SanitizerInterceptor::prepareLaunch(ur_queue_handle_t Queue, return UR_RESULT_SUCCESS; } +std::vector> +SanitizerInterceptor::findAllocInfoByAddress(uptr Address, + ur_context_handle_t Context, + ur_device_handle_t Device) { + std::vector> Result; + auto current = std::make_shared(USMAllocInfo{Address}); + + std::shared_lock Guard(m_AllocationsMapMutex); + + auto It = std::lower_bound( + m_AllocationsMap.begin(), m_AllocationsMap.end(), Address, + [](const std::shared_ptr &AllocInfo, uptr Addr) { + return (AllocInfo->AllocBegin + AllocInfo->AllocSize) < Addr; + }); + for (; It != m_AllocationsMap.end(); ++It) { + auto AI = *It; + if (AI->AllocBegin > Address) { + break; + } + if (Context && AI->Context != Context) { + continue; + } + if (Device && AI->Device != Device) { + continue; + } + Result.emplace_back(*It); + } + return Result; +} + LaunchInfo::~LaunchInfo() { if (LocalShadowOffset) { [[maybe_unused]] auto Result = diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 8902c422ea..484d14c8ee 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -18,19 +18,26 @@ #include #include +#include #include +#include #include namespace ur_sanitizer_layer { -enum MemoryType { DEVICE_USM, SHARED_USM, HOST_USM, MEM_BUFFER, RELEASED }; +enum MemoryType { DEVICE_USM, SHARED_USM, HOST_USM, MEM_BUFFER }; struct USMAllocInfo { - uptr AllocBegin; - uptr UserBegin; - uptr UserEnd; - size_t AllocSize; - MemoryType Type; + uptr AllocBegin = 0; + uptr UserBegin = 0; + uptr UserEnd = 0; + size_t AllocSize = 0; + + MemoryType Type = MemoryType::DEVICE_USM; + bool IsReleased = false; + + ur_context_handle_t Context = nullptr; + ur_device_handle_t Device = nullptr; StackTrace AllocStack; StackTrace ReleaseStack; @@ -68,21 +75,10 @@ struct ContextInfo { return QueueMap[Queue]; } - std::shared_ptr getUSMAllocInfo(uptr Address) { - std::shared_lock Guard(Mutex); - assert(AllocatedUSMMap.find(Address) != AllocatedUSMMap.end()); - return AllocatedUSMMap[Address]; - } - ur_shared_mutex Mutex; std::unordered_map> DeviceMap; std::unordered_map> QueueMap; - - /// key: USMAllocInfo.AllocBegin - /// value: USMAllocInfo - /// Use AllocBegin as key can help to detect underflow pointer - std::map> AllocatedUSMMap; }; struct LaunchInfo { @@ -130,6 +126,10 @@ class SanitizerInterceptor { ur_result_t eraseQueue(ur_context_handle_t Context, ur_queue_handle_t Queue); + std::vector> + findAllocInfoByAddress(uptr Address, ur_context_handle_t Context, + ur_device_handle_t Device); + private: ur_result_t updateShadowMemory(ur_queue_handle_t Queue); ur_result_t enqueueAllocInfo(ur_context_handle_t Context, @@ -163,6 +163,23 @@ class SanitizerInterceptor { m_ContextMap; ur_shared_mutex m_ContextMapMutex; + struct USMAllocInfoCompare { + bool operator()(const std::shared_ptr &lhs, + const std::shared_ptr &rhs) const { + auto p1 = std::make_pair(lhs->AllocBegin, + lhs->AllocBegin + lhs->AllocSize); + auto p2 = std::make_pair(rhs->AllocBegin, + rhs->AllocBegin + rhs->AllocSize); + return p1 < p2; + } + }; + + using AllocaionRangSet = + std::multiset, USMAllocInfoCompare>; + + AllocaionRangSet m_AllocationsMap; + ur_shared_mutex m_AllocationsMapMutex; + bool m_IsInASanContext; bool m_ShadowMemInited; }; diff --git a/source/loader/layers/sanitizer/common.hpp b/source/loader/layers/sanitizer/common.hpp index 001d4f2e5d..b9d39e95cb 100644 --- a/source/loader/layers/sanitizer/common.hpp +++ b/source/loader/layers/sanitizer/common.hpp @@ -93,11 +93,15 @@ inline constexpr uptr ComputeRZLog(uptr user_requested_size) { return Result; \ } -#ifndef NDEBUG -#define UR_ASSERT_EQ(Call, Result) assert(Call == Result) -#else -#define UR_ASSERT_EQ(Call, Result) (void)Call -#endif +struct AddressInfo { + uptr offset; + std::string module; + std::string file; + std::string function; + int line; + int column; + std::string debug; +}; bool IsInASanContext(); diff --git a/source/loader/layers/sanitizer/device_sanitizer_report.hpp b/source/loader/layers/sanitizer/device_sanitizer_report.hpp index 11ae721434..8993c16b89 100644 --- a/source/loader/layers/sanitizer/device_sanitizer_report.hpp +++ b/source/loader/layers/sanitizer/device_sanitizer_report.hpp @@ -50,6 +50,7 @@ struct DeviceSanitizerReport { uint64_t LID1 = 0; uint64_t LID2 = 0; + uint64_t Addr = 0; bool IsWrite = false; uint32_t AccessSize = 0; DeviceSanitizerMemoryType MemoryType; diff --git a/source/loader/layers/sanitizer/linux/backtrace_lin.cpp b/source/loader/layers/sanitizer/linux/backtrace.cpp similarity index 57% rename from source/loader/layers/sanitizer/linux/backtrace_lin.cpp rename to source/loader/layers/sanitizer/linux/backtrace.cpp index 6748eed667..732d35adb4 100644 --- a/source/loader/layers/sanitizer/linux/backtrace_lin.cpp +++ b/source/loader/layers/sanitizer/linux/backtrace.cpp @@ -8,11 +8,24 @@ * */ #include "stacktrace.hpp" +#include "ur_sanitizer_layer.hpp" +#include #include +#include namespace ur_sanitizer_layer { +bool ExtractSymbolInfo(const char *symbol, AddressInfo &info) { + info.debug = std::string(symbol); + + auto s1 = std::strrchr(symbol, '('); + info.module = std::string(symbol, s1 - symbol); + auto s2 = std::strrchr(symbol, '['); + info.offset = std::stoull(s2 + 1, nullptr, 16); + return true; +} + StackTrace GetCurrentBacktrace() { void *backtraceFrames[MAX_BACKTRACE_FRAMES]; int frameCount = backtrace(backtraceFrames, MAX_BACKTRACE_FRAMES); @@ -24,7 +37,11 @@ StackTrace GetCurrentBacktrace() { StackTrace stack; for (int i = 0; i < frameCount; i++) { - stack.stack.emplace_back(backtraceStr[i]); + AddressInfo addr_info; + if (!ExtractSymbolInfo(backtraceStr[i], addr_info)) { + continue; + } + stack.stack.emplace_back(std::move(addr_info)); } free(backtraceStr); diff --git a/source/loader/layers/sanitizer/linux/symbolizer_llvm.cpp b/source/loader/layers/sanitizer/linux/symbolizer_llvm.cpp new file mode 100644 index 0000000000..8e57a981cf --- /dev/null +++ b/source/loader/layers/sanitizer/linux/symbolizer_llvm.cpp @@ -0,0 +1,64 @@ +/* + * + * Copyright (C) 2023 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file symbolizer_llvm.cpp + * + */ + +#include "symbolizer_llvm.hpp" +#include "ur_sanitizer_layer.hpp" + +#include +#include + +namespace ur_sanitizer_layer { + +std::string exec(const char *cmd) { + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(cmd, "r"), pclose); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + return result; +} + +bool ExtractInfo(const std::string &output, AddressInfo *Info) { + auto p1 = output.find('\n'); + std::string function = output.substr(0, p1); + auto p2 = output.find(':', ++p1); + std::string file = output.substr(p1, p2 - p1); + auto p3 = output.find(':', ++p2); + int line = std::stoi(output.substr(p2, p3 - p2)); + int column = std::stoi(output.substr(++p3)); + if (function != "??") { + Info->function = std::move(function); + } + if (file != "??") { + Info->file = std::move(file); + } + Info->line = line; + Info->column = column; + return true; +} + +LLVMSymbolizer::LLVMSymbolizer(const char *path) {} + +bool LLVMSymbolizer::SymbolizePC(AddressInfo *Info) { + std::stringstream ss; + ss << "llvm-symbolizer --obj=" << Info->module << " " << Info->offset; + auto result = exec(ss.str().c_str()); + // context.logger.debug("llvm-symbolizer: {}", result); + ExtractInfo(result, Info); + return true; +} + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/stacktrace.cpp b/source/loader/layers/sanitizer/stacktrace.cpp index 9b982e2e98..737c6d83ca 100644 --- a/source/loader/layers/sanitizer/stacktrace.cpp +++ b/source/loader/layers/sanitizer/stacktrace.cpp @@ -13,18 +13,47 @@ #pragma once #include "stacktrace.hpp" +#include "symbolizer_llvm.hpp" #include "ur_sanitizer_layer.hpp" namespace ur_sanitizer_layer { #define MAX_BACKTRACE_FRAMES 64 -void StackTrace::Print() const { +std::string getFileName(const std::string &FilePath) { + auto p = FilePath.find_last_of('/'); + return FilePath.substr(p + 1); +} + +bool startWith(const std::string &Str, const char *Pattern) { + return Str.rfind(Pattern, 0) == 0; +} + +void StackTrace::Print() { if (!stack.size()) { context.logger.always(" failed to acquire backtrace"); } - for (unsigned i = 0; i < stack.size(); ++i) { - context.logger.always(" #{} {}", i, stack[i]); + LLVMSymbolizer symbolizer(""); + unsigned index = 0; + for (auto &Addr : stack) { + auto ModuleFile = getFileName(Addr.module); + if (startWith(ModuleFile, "libsycl.so") || + startWith(ModuleFile, "libpi_unified_runtime.so") || + startWith(ModuleFile, "libur_loader.so")) { + continue; + } + symbolizer.SymbolizePC(&Addr); + + if (!Addr.file.empty()) { + context.logger.always(" #{} {} in {} {}:{}:{}", index, + (void *)Addr.offset, Addr.function, Addr.file, + Addr.line, Addr.column); + } else { + context.logger.always(" #{} {} in {} {}", index, + (void *)Addr.offset, Addr.function, + Addr.module); + } + ++index; } context.logger.always(""); } diff --git a/source/loader/layers/sanitizer/stacktrace.hpp b/source/loader/layers/sanitizer/stacktrace.hpp index 897b9b1001..046b3e46b0 100644 --- a/source/loader/layers/sanitizer/stacktrace.hpp +++ b/source/loader/layers/sanitizer/stacktrace.hpp @@ -12,6 +12,8 @@ #pragma once +#include "common.hpp" + #include #include @@ -19,12 +21,10 @@ namespace ur_sanitizer_layer { #define MAX_BACKTRACE_FRAMES 64 -using BacktraceLine = std::string; - struct StackTrace { - std::vector stack; + std::vector stack; - void Print() const; + void Print(); }; StackTrace GetCurrentBacktrace(); diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.hpp b/source/loader/layers/sanitizer/symbolizer_llvm.hpp new file mode 100644 index 0000000000..7588f27119 --- /dev/null +++ b/source/loader/layers/sanitizer/symbolizer_llvm.hpp @@ -0,0 +1,30 @@ +/* + * + * Copyright (C) 2023 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file symbolizer_llvm.hpp + * + */ + +#pragma once + +#include "common.hpp" + +namespace ur_sanitizer_layer { + +class SymbolizerTool { + virtual bool SymbolizePC(AddressInfo *Info) { return false; } +}; + +class LLVMSymbolizer final : public SymbolizerTool { + public: + explicit LLVMSymbolizer(const char *path); + + bool SymbolizePC(AddressInfo *Info) override; +}; + +} // namespace ur_sanitizer_layer From 3bbcf25a29d540a5ceeaf3e46c6a02d5bef640f7 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Mon, 19 Feb 2024 23:45:18 -0800 Subject: [PATCH 08/42] refactor asan_interceptor --- source/loader/CMakeLists.txt | 6 +- .../layers/sanitizer/asan_interceptor.cpp | 360 +++++++----------- .../layers/sanitizer/asan_interceptor.hpp | 147 +++++-- .../layers/sanitizer/asan_shadow_setup.cpp | 137 +++++++ .../layers/sanitizer/asan_shadow_setup.hpp | 26 ++ source/loader/layers/sanitizer/common.hpp | 18 +- .../{san_utils.cpp => sanitizer_utils.cpp} | 36 +- source/loader/layers/sanitizer/stacktrace.hpp | 3 +- source/loader/layers/sanitizer/ur_sanddi.cpp | 148 ++----- 9 files changed, 451 insertions(+), 430 deletions(-) create mode 100644 source/loader/layers/sanitizer/asan_shadow_setup.cpp create mode 100644 source/loader/layers/sanitizer/asan_shadow_setup.hpp rename source/loader/layers/sanitizer/linux/{san_utils.cpp => sanitizer_utils.cpp} (62%) diff --git a/source/loader/CMakeLists.txt b/source/loader/CMakeLists.txt index 7a77f7c63e..6057bfebf1 100644 --- a/source/loader/CMakeLists.txt +++ b/source/loader/CMakeLists.txt @@ -115,14 +115,16 @@ if(UR_ENABLE_SANITIZER) ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanddi.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/symbolizer_llvm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/symbolizer_llvm.hpp ) target_sources(ur_loader PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/san_utils.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/sanitizer_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/backtrace.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/symbolizer_llvm.cpp ) target_include_directories(ur_loader PRIVATE diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 96d956d7c3..ea95d2ebc5 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -12,10 +12,10 @@ */ #include "asan_interceptor.hpp" +#include "asan_shadow_setup.hpp" #include "device_sanitizer_report.hpp" #include "stacktrace.hpp" #include "ur_api.h" -#include "ur_sanitizer_layer.hpp" namespace ur_sanitizer_layer { @@ -64,7 +64,7 @@ ur_context_handle_t getContext(ur_queue_handle_t Queue) { [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( Queue, UR_QUEUE_INFO_CONTEXT, sizeof(ur_context_handle_t), &Context, nullptr); - assert(Result == UR_RESULT_SUCCESS); + assert(Result == UR_RESULT_SUCCESS && "getContext() failed"); return Context; } @@ -73,7 +73,7 @@ ur_device_handle_t getDevice(ur_queue_handle_t Queue) { [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( Queue, UR_QUEUE_INFO_DEVICE, sizeof(ur_device_handle_t), &Device, nullptr); - assert(Result == UR_RESULT_SUCCESS); + assert(Result == UR_RESULT_SUCCESS && "getDevice() failed"); return Device; } @@ -82,7 +82,7 @@ ur_program_handle_t getProgram(ur_kernel_handle_t Kernel) { [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( Kernel, UR_KERNEL_INFO_PROGRAM, sizeof(ur_program_handle_t), &Program, nullptr); - assert(Result == UR_RESULT_SUCCESS); + assert(Result == UR_RESULT_SUCCESS && "getProgram() failed"); return Program; } @@ -91,21 +91,21 @@ size_t getLocalMemorySize(ur_device_handle_t Device) { [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( Device, UR_DEVICE_INFO_LOCAL_MEM_SIZE, sizeof(LocalMemorySize), &LocalMemorySize, nullptr); - assert(Result == UR_RESULT_SUCCESS); + assert(Result == UR_RESULT_SUCCESS && "getLocalMemorySize() failed"); return LocalMemorySize; } std::string getKernelName(ur_kernel_handle_t Kernel) { size_t KernelNameSize = 0; - [[maybe_unused]] auto Res = context.urDdiTable.Kernel.pfnGetInfo( + [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( Kernel, UR_KERNEL_INFO_FUNCTION_NAME, 0, nullptr, &KernelNameSize); - assert(Res == UR_RESULT_SUCCESS); + assert(Result == UR_RESULT_SUCCESS && "getKernelName() failed"); std::vector KernelNameBuf(KernelNameSize); - Res = context.urDdiTable.Kernel.pfnGetInfo( + Result = context.urDdiTable.Kernel.pfnGetInfo( Kernel, UR_KERNEL_INFO_FUNCTION_NAME, KernelNameSize, KernelNameBuf.data(), nullptr); - assert(Res == UR_RESULT_SUCCESS); + assert(Result == UR_RESULT_SUCCESS && "getKernelName() failed"); return std::string(KernelNameBuf.data(), KernelNameSize - 1); } @@ -116,10 +116,27 @@ ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, [[maybe_unused]] auto Result = context.urDdiTable.USM.pfnGetMemAllocInfo( Context, MemPtr, UR_USM_ALLOC_INFO_DEVICE, sizeof(Device), &Device, nullptr); - assert(Result == UR_RESULT_SUCCESS); + assert(Result == UR_RESULT_SUCCESS && "getUSMAllocDevice() failed"); return Device; } +DeviceType getDeviceType(ur_device_handle_t Device) { + ur_device_type_t DeviceType; + [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( + Device, UR_DEVICE_INFO_TYPE, sizeof(DeviceType), &DeviceType, nullptr); + assert(Result == UR_RESULT_SUCCESS && "getDeviceType() failed"); + switch (DeviceType) { + case UR_DEVICE_TYPE_CPU: + return DeviceType::CPU; + case UR_DEVICE_TYPE_GPU: { + // TODO: Check device vendor + return DeviceType::GPU_PVC; + } + default: + return DeviceType::UNKNOWN; + } +} + const char *getFormatString(MemoryType MemoryType) { switch (MemoryType) { case MemoryType::DEVICE_USM: @@ -221,9 +238,8 @@ SanitizerInterceptor::SanitizerInterceptor() m_ShadowMemInited(m_IsInASanContext) {} SanitizerInterceptor::~SanitizerInterceptor() { - if (!m_IsInASanContext && m_ShadowMemInited && !DestroyShadowMem()) { - context.logger.error("Failed to destroy shadow memory"); - } + DestroyShadowMemoryOnCPU(); + DestroyShadowMemoryOnPVC(); } /// The memory chunk allocated from the underlying allocator looks like this: @@ -241,10 +257,8 @@ ur_result_t SanitizerInterceptor::allocateMemory( assert(Alignment == 0 || IsPowerOfTwo(Alignment)); auto ContextInfo = getContextInfo(Context); - std::shared_ptr DeviceInfo; - if (Device) { - DeviceInfo = ContextInfo->getDeviceInfo(Device); - } + std::shared_ptr DeviceInfo = + Device ? getDeviceInfo(Device) : nullptr; if (Alignment == 0) { Alignment = @@ -298,15 +312,10 @@ ur_result_t SanitizerInterceptor::allocateMemory( {}}); // For updating shadow memory - if (DeviceInfo) { // device/shared USM - std::scoped_lock Guard(DeviceInfo->Mutex); - DeviceInfo->AllocInfos.emplace_back(AllocInfo); - } else { // host USM's AllocInfo needs to insert into all devices - for (auto &pair : ContextInfo->DeviceMap) { - auto DeviceInfo = pair.second; - std::scoped_lock Guard(DeviceInfo->Mutex); - DeviceInfo->AllocInfos.emplace_back(AllocInfo); - } + if (Device) { // Device/Shared USM + ContextInfo->insertAllocInfo({Device}, AllocInfo); + } else { // Host USM + ContextInfo->insertAllocInfo(ContextInfo->DeviceList, AllocInfo); } // For memory release @@ -327,8 +336,6 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, void *Ptr) { auto ContextInfo = getContextInfo(Context); - std::shared_lock Guard(ContextInfo->Mutex); - auto Addr = reinterpret_cast(Ptr); auto AllocInfos = findAllocInfoByAddress(Addr, Context, nullptr); @@ -358,6 +365,9 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, auto Device = getUSMAllocDevice(Context, (const void *)AllocInfo->AllocBegin); + // TODO: Check Device + // TODO: Quarantine Cache + // auto Res = // context.urDdiTable.USM.pfnFree(Context, (void *)AllocInfo->AllocBegin); // if (Res != UR_RESULT_SUCCESS) { @@ -365,15 +375,9 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, // } if (AllocInfo->Type == MemoryType::HOST_USM) { - for (auto &pair : ContextInfo->DeviceMap) { - auto DeviceInfo = pair.second; - std::scoped_lock Guard(DeviceInfo->Mutex); - DeviceInfo->AllocInfos.emplace_back(AllocInfo); - } + ContextInfo->insertAllocInfo(ContextInfo->DeviceList, AllocInfo); } else { - auto DeviceInfo = ContextInfo->getDeviceInfo(Device); - std::scoped_lock Guard(DeviceInfo->Mutex); - DeviceInfo->AllocInfos.emplace_back(AllocInfo); + ContextInfo->insertAllocInfo({Device}, AllocInfo); } } @@ -382,21 +386,21 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, ur_result_t SanitizerInterceptor::preLaunchKernel(ur_kernel_handle_t Kernel, ur_queue_handle_t Queue, - ur_event_handle_t &Event, LaunchInfo &LaunchInfo, uint32_t numWorkgroup) { - UR_CALL(prepareLaunch(Queue, Kernel, LaunchInfo, numWorkgroup)); - - UR_CALL(updateShadowMemory(Queue)); - - // Return LastEvent in QueueInfo auto Context = getContext(Queue); + auto Device = getDevice(Queue); auto ContextInfo = getContextInfo(Context); - auto QueueInfo = ContextInfo->getQueueInfo(Queue); + auto DeviceInfo = getDeviceInfo(Device); + + ManagedQueue InternalQueue(Context, Device); - std::scoped_lock Guard(QueueInfo->Mutex); - Event = QueueInfo->LastEvent; - QueueInfo->LastEvent = nullptr; + UR_CALL(prepareLaunch(Context, DeviceInfo, InternalQueue, Kernel, + LaunchInfo, numWorkgroup)); + + UR_CALL(updateShadowMemory(ContextInfo, DeviceInfo, InternalQueue)); + + UR_CALL(context.urDdiTable.Queue.pfnFinish(InternalQueue)); return UR_RESULT_SUCCESS; } @@ -427,65 +431,23 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, } } -ur_result_t SanitizerInterceptor::allocShadowMemory( - ur_context_handle_t Context, std::shared_ptr &DeviceInfo) { - if (DeviceInfo->Type == DeviceType::CPU) { - if (!m_IsInASanContext) { - static std::once_flag OnceFlag; - bool Result = true; - std::call_once(OnceFlag, [&]() { - Result = m_ShadowMemInited = SetupShadowMem(); - }); - - if (!Result) { - context.logger.error("Failed to allocate shadow memory"); - return UR_RESULT_ERROR_OUT_OF_RESOURCES; - } - } - - DeviceInfo->ShadowOffset = LOW_SHADOW_BEGIN; - DeviceInfo->ShadowOffsetEnd = HIGH_SHADOW_END; - } else if (DeviceInfo->Type == DeviceType::GPU_PVC) { - /// SHADOW MEMORY MAPPING (PVC, with CPU 47bit) - /// Host/Shared USM : 0x0 ~ 0x0fff_ffff_ffff - /// ? : 0x1000_0000_0000 ~ 0x1fff_ffff_ffff - /// Device USM : 0x2000_0000_0000 ~ 0x3fff_ffff_ffff - constexpr size_t SHADOW_SIZE = 1ULL << 46; - // FIXME: Currently, Level-Zero doesn't create independent VAs for each contexts, - // which will cause out-of-resource error when users use multiple contexts - static uptr ShadowOffset, ShadowOffsetEnd; - - if (!ShadowOffset) { - // TODO: Protect Bad Zone - auto Result = context.urDdiTable.VirtualMem.pfnReserve( - Context, nullptr, SHADOW_SIZE, (void **)&ShadowOffset); - if (Result != UR_RESULT_SUCCESS) { - context.logger.error( - "Failed to allocate shadow memory on PVC: {}", Result); - return Result; - } - ShadowOffsetEnd = ShadowOffset + SHADOW_SIZE; - } - - DeviceInfo->ShadowOffset = ShadowOffset; - DeviceInfo->ShadowOffsetEnd = ShadowOffsetEnd; +ur_result_t DeviceInfo::allocShadowMemory(ur_context_handle_t Context) { + if (Type == DeviceType::CPU) { + UR_CALL(SetupShadowMemoryOnCPU(ShadowOffset, ShadowOffsetEnd)); + } else if (Type == DeviceType::GPU_PVC) { + UR_CALL(SetupShadowMemoryOnPVC(Context, ShadowOffset, ShadowOffsetEnd)); } else { context.logger.error("Unsupport device type"); return UR_RESULT_ERROR_INVALID_ARGUMENT; } - context.logger.info("ShadowMemory(Global): {} - {}", - (void *)DeviceInfo->ShadowOffset, - (void *)DeviceInfo->ShadowOffsetEnd); + context.logger.info("ShadowMemory(Global): {} - {}", (void *)ShadowOffset, + (void *)ShadowOffsetEnd); return UR_RESULT_SUCCESS; } ur_result_t SanitizerInterceptor::enqueueMemSetShadow( - ur_context_handle_t Context, ur_device_handle_t Device, - ur_queue_handle_t Queue, uptr Ptr, uptr Size, u8 Value, - ur_event_handle_t DepEvent, ur_event_handle_t *OutEvent) { - - auto ContextInfo = getContextInfo(Context); - auto DeviceInfo = ContextInfo->getDeviceInfo(Device); + ur_context_handle_t Context, std::shared_ptr &DeviceInfo, + ur_queue_handle_t Queue, uptr Ptr, uptr Size, u8 Value) { if (DeviceInfo->Type == DeviceType::CPU) { uptr ShadowBegin = MemToShadow_CPU(DeviceInfo->ShadowOffset, Ptr); @@ -512,18 +474,12 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( uptr ShadowEnd = MemToShadow_PVC(DeviceInfo->ShadowOffset, Ptr + Size - 1); - uint32_t NumEventsInWaitList = DepEvent ? 1 : 0; - const ur_event_handle_t *EventsWaitList = - DepEvent ? &DepEvent : nullptr; - ur_event_handle_t InternalEvent{}; - ur_event_handle_t *Event = OutEvent ? OutEvent : &InternalEvent; - { - static const size_t PageSize = [Context, Device]() { + static const size_t PageSize = [Context, DeviceInfo]() { size_t Size; [[maybe_unused]] auto Result = context.urDdiTable.VirtualMem.pfnGranularityGetInfo( - Context, Device, + Context, DeviceInfo->Handle, UR_VIRTUAL_MEM_GRANULARITY_INFO_RECOMMENDED, sizeof(Size), &Size, nullptr); assert(Result == UR_RESULT_SUCCESS); @@ -540,7 +496,8 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( MappedPtr <= ShadowEnd; MappedPtr += PageSize) { if (!PhysicalMem) { auto URes = context.urDdiTable.PhysicalMem.pfnCreate( - Context, Device, PageSize, &Desc, &PhysicalMem); + Context, DeviceInfo->Handle, PageSize, &Desc, + &PhysicalMem); if (URes != UR_RESULT_SUCCESS) { context.logger.error("urPhysicalMemCreate(): {}", URes); return URes; @@ -567,15 +524,12 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( const char Pattern[] = {0}; auto URes = context.urDdiTable.Enqueue.pfnUSMFill( - Queue, (void *)MappedPtr, 1, Pattern, PageSize, - NumEventsInWaitList, EventsWaitList, Event); + Queue, (void *)MappedPtr, 1, Pattern, PageSize, 0, + nullptr, nullptr); if (URes != UR_RESULT_SUCCESS) { context.logger.error("urEnqueueUSMFill(): {}", URes); return URes; } - - NumEventsInWaitList = 1; - EventsWaitList = Event; } } } @@ -583,7 +537,7 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( const char Pattern[] = {(char)Value}; auto URes = context.urDdiTable.Enqueue.pfnUSMFill( Queue, (void *)ShadowBegin, 1, Pattern, ShadowEnd - ShadowBegin + 1, - NumEventsInWaitList, EventsWaitList, Event); + 0, nullptr, nullptr); context.logger.debug( "enqueueMemSetShadow (addr={}, count={}, value={}): {}", (void *)ShadowBegin, ShadowEnd - ShadowBegin + 1, @@ -607,9 +561,8 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( /// /// ref: https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm#mapping ur_result_t SanitizerInterceptor::enqueueAllocInfo( - ur_context_handle_t Context, ur_device_handle_t Device, - ur_queue_handle_t Queue, std::shared_ptr &AllocInfo, - ur_event_handle_t &LastEvent) { + ur_context_handle_t Context, std::shared_ptr &DeviceInfo, + ur_queue_handle_t Queue, std::shared_ptr &AllocInfo) { if (AllocInfo->IsReleased) { int ShadowByte; switch (AllocInfo->Type) { @@ -629,16 +582,16 @@ ur_result_t SanitizerInterceptor::enqueueAllocInfo( ShadowByte = 0xff; assert(false && "Unknow AllocInfo Type"); } - UR_CALL(enqueueMemSetShadow(Context, Device, Queue, + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AllocInfo->AllocBegin, AllocInfo->AllocSize, - ShadowByte, LastEvent, &LastEvent)); + ShadowByte)); return UR_RESULT_SUCCESS; } // Init zero - UR_CALL(enqueueMemSetShadow(Context, Device, Queue, AllocInfo->AllocBegin, - AllocInfo->AllocSize, 0, LastEvent, - &LastEvent)); + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, + AllocInfo->AllocBegin, AllocInfo->AllocSize, + 0)); uptr TailBegin = RoundUpTo(AllocInfo->UserEnd, ASAN_SHADOW_GRANULARITY); uptr TailEnd = AllocInfo->AllocBegin + AllocInfo->AllocSize; @@ -647,9 +600,9 @@ ur_result_t SanitizerInterceptor::enqueueAllocInfo( if (TailBegin != AllocInfo->UserEnd) { auto Value = AllocInfo->UserEnd - RoundDownTo(AllocInfo->UserEnd, ASAN_SHADOW_GRANULARITY); - UR_CALL(enqueueMemSetShadow(Context, Device, Queue, AllocInfo->UserEnd, - 1, static_cast(Value), LastEvent, - &LastEvent)); + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, + AllocInfo->UserEnd, 1, + static_cast(Value))); } int ShadowByte; @@ -672,51 +625,45 @@ ur_result_t SanitizerInterceptor::enqueueAllocInfo( } // Left red zone - UR_CALL(enqueueMemSetShadow(Context, Device, Queue, AllocInfo->AllocBegin, - AllocInfo->UserBegin - AllocInfo->AllocBegin, - ShadowByte, LastEvent, &LastEvent)); + UR_CALL(enqueueMemSetShadow( + Context, DeviceInfo, Queue, AllocInfo->AllocBegin, + AllocInfo->UserBegin - AllocInfo->AllocBegin, ShadowByte)); // Right red zone - UR_CALL(enqueueMemSetShadow(Context, Device, Queue, TailBegin, - TailEnd - TailBegin, ShadowByte, LastEvent, - &LastEvent)); + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, TailBegin, + TailEnd - TailBegin, ShadowByte)); return UR_RESULT_SUCCESS; } -ur_result_t SanitizerInterceptor::updateShadowMemory(ur_queue_handle_t Queue) { - auto Context = getContext(Queue); - auto Device = getDevice(Queue); - assert(Device != nullptr); - - auto ContextInfo = getContextInfo(Context); - - auto DeviceInfo = ContextInfo->getDeviceInfo(Device); - auto QueueInfo = ContextInfo->getQueueInfo(Queue); - - std::unique_lock DeviceGuard(DeviceInfo->Mutex, - std::defer_lock); - std::scoped_lock, ur_mutex> Guard( - DeviceGuard, QueueInfo->Mutex); - - ur_event_handle_t LastEvent = QueueInfo->LastEvent; +ur_result_t SanitizerInterceptor::updateShadowMemory( + std::shared_ptr &ContextInfo, + std::shared_ptr &DeviceInfo, ur_queue_handle_t Queue) { + auto &AllocInfos = ContextInfo->AllocInfosMap[DeviceInfo->Handle]; + std::scoped_lock Guard(AllocInfos.Mutex); - for (auto &AllocInfo : DeviceInfo->AllocInfos) { - UR_CALL(enqueueAllocInfo(Context, Device, Queue, AllocInfo, LastEvent)); + for (auto &AllocInfo : AllocInfos.List) { + UR_CALL(enqueueAllocInfo(ContextInfo->Handle, DeviceInfo, Queue, + AllocInfo)); } - DeviceInfo->AllocInfos.clear(); - - QueueInfo->LastEvent = LastEvent; + AllocInfos.List.clear(); return UR_RESULT_SUCCESS; } -ur_result_t SanitizerInterceptor::insertContext(ur_context_handle_t Context) { - auto ContextInfo = std::make_shared(); - +ur_result_t +SanitizerInterceptor::insertContext(ur_context_handle_t Context, + std::shared_ptr &CI) { std::scoped_lock Guard(m_ContextMapMutex); - assert(m_ContextMap.find(Context) == m_ContextMap.end()); - m_ContextMap.emplace(Context, std::move(ContextInfo)); + + if (m_ContextMap.find(Context) != m_ContextMap.end()) { + CI = m_ContextMap.at(Context); + return UR_RESULT_SUCCESS; + } + + CI = std::make_shared(Context); + + m_ContextMap.emplace(Context, std::move(CI)); return UR_RESULT_SUCCESS; } @@ -729,95 +676,60 @@ ur_result_t SanitizerInterceptor::eraseContext(ur_context_handle_t Context) { return UR_RESULT_SUCCESS; } -ur_result_t SanitizerInterceptor::insertDevice(ur_context_handle_t Context, - ur_device_handle_t Device) { - auto DeviceInfo = std::make_shared(); +ur_result_t +SanitizerInterceptor::insertDevice(ur_device_handle_t Device, + std::shared_ptr &DI) { + std::scoped_lock Guard(m_DeviceMapMutex); + + if (m_DeviceMap.find(Device) != m_DeviceMap.end()) { + DI = m_DeviceMap.at(Device); + return UR_RESULT_SUCCESS; + } + + DI = std::make_shared(Device); // Query device type - ur_device_type_t DeviceType; - UR_CALL(context.urDdiTable.Device.pfnGetInfo( - Device, UR_DEVICE_INFO_TYPE, sizeof(DeviceType), &DeviceType, nullptr)); - switch (DeviceType) { - case UR_DEVICE_TYPE_CPU: - DeviceInfo->Type = DeviceType::CPU; - break; - case UR_DEVICE_TYPE_GPU: - DeviceInfo->Type = DeviceType::GPU_PVC; - break; - default: - DeviceInfo->Type = DeviceType::UNKNOWN; + DI->Type = getDeviceType(Device); + if (DI->Type == DeviceType::UNKNOWN) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; } // Query alignment UR_CALL(context.urDdiTable.Device.pfnGetInfo( - Device, UR_DEVICE_INFO_MEM_BASE_ADDR_ALIGN, - sizeof(DeviceInfo->Alignment), &DeviceInfo->Alignment, nullptr)); + Device, UR_DEVICE_INFO_MEM_BASE_ADDR_ALIGN, sizeof(DI->Alignment), + &DI->Alignment, nullptr)); - // Allocate shadow memory - UR_CALL(allocShadowMemory(Context, DeviceInfo)); - - auto ContextInfo = getContextInfo(Context); - std::scoped_lock Guard(ContextInfo->Mutex); - ContextInfo->DeviceMap.emplace(Device, std::move(DeviceInfo)); + m_DeviceMap.emplace(Device, std::move(DI)); return UR_RESULT_SUCCESS; } -ur_result_t SanitizerInterceptor::insertQueue(ur_context_handle_t Context, - ur_queue_handle_t Queue) { - auto QueueInfo = std::make_shared(); - QueueInfo->LastEvent = nullptr; - - auto ContextInfo = getContextInfo(Context); - std::scoped_lock Guard(ContextInfo->Mutex); - ContextInfo->QueueMap.emplace(Queue, std::move(QueueInfo)); - - return UR_RESULT_SUCCESS; -} - -ur_result_t SanitizerInterceptor::eraseQueue(ur_context_handle_t Context, - ur_queue_handle_t Queue) { - auto ContextInfo = getContextInfo(Context); - std::scoped_lock Guard(ContextInfo->Mutex); - assert(ContextInfo->QueueMap.find(Queue) != ContextInfo->QueueMap.end()); - ContextInfo->QueueMap.erase(Queue); +ur_result_t SanitizerInterceptor::eraseDevice(ur_device_handle_t Device) { + std::scoped_lock Guard(m_DeviceMapMutex); + assert(m_DeviceMap.find(Device) != m_DeviceMap.end()); + m_DeviceMap.erase(Device); + // TODO: Remove devices in each context return UR_RESULT_SUCCESS; } -ur_result_t SanitizerInterceptor::prepareLaunch(ur_queue_handle_t Queue, - ur_kernel_handle_t Kernel, - LaunchInfo &LaunchInfo, - uint32_t numWorkgroup) { - auto Context = getContext(Queue); - auto Device = getDevice(Queue); +ur_result_t SanitizerInterceptor::prepareLaunch( + ur_context_handle_t Context, std::shared_ptr &DeviceInfo, + ur_queue_handle_t Queue, ur_kernel_handle_t Kernel, LaunchInfo &LaunchInfo, + uint32_t numWorkgroup) { auto Program = getProgram(Kernel); - LaunchInfo.Context = Context; - - auto ContextInfo = getContextInfo(Context); - auto DeviceInfo = ContextInfo->getDeviceInfo(Device); - auto QueueInfo = ContextInfo->getQueueInfo(Queue); - - std::scoped_lock Guard(QueueInfo->Mutex); - ur_event_handle_t LastEvent = QueueInfo->LastEvent; - do { // Set global variable to program auto EnqueueWriteGlobal = [&](const char *Name, const void *Value) { - ur_event_handle_t NewEvent{}; - uint32_t NumEvents = LastEvent ? 1 : 0; - const ur_event_handle_t *EventsList = - LastEvent ? &LastEvent : nullptr; auto Result = context.urDdiTable.Enqueue.pfnDeviceGlobalVariableWrite( - Queue, Program, Name, false, sizeof(uptr), 0, Value, - NumEvents, EventsList, &NewEvent); + Queue, Program, Name, false, sizeof(uptr), 0, Value, 0, + nullptr, nullptr); if (Result != UR_RESULT_SUCCESS) { context.logger.warning("Device Global[{}] Write Failed: {}", Name, Result); return false; } - LastEvent = NewEvent; return true; }; @@ -835,7 +747,7 @@ ur_result_t SanitizerInterceptor::prepareLaunch(ur_queue_handle_t Queue, } // Write shadow memory offset for local memory - auto LocalMemorySize = getLocalMemorySize(Device); + auto LocalMemorySize = getLocalMemorySize(DeviceInfo->Handle); auto LocalShadowMemorySize = (numWorkgroup * LocalMemorySize) >> ASAN_SHADOW_SCALE; @@ -846,7 +758,7 @@ ur_result_t SanitizerInterceptor::prepareLaunch(ur_queue_handle_t Queue, ur_usm_desc_t Desc{UR_STRUCTURE_TYPE_USM_HOST_DESC, nullptr, 0, 0}; auto Result = context.urDdiTable.USM.pfnDeviceAlloc( - Context, Device, &Desc, nullptr, LocalShadowMemorySize, + Context, DeviceInfo->Handle, &Desc, nullptr, LocalShadowMemorySize, (void **)&LaunchInfo.LocalShadowOffset); if (Result != UR_RESULT_SUCCESS) { context.logger.error( @@ -864,20 +776,15 @@ ur_result_t SanitizerInterceptor::prepareLaunch(ur_queue_handle_t Queue, &LaunchInfo.LocalShadowOffsetEnd); { - ur_event_handle_t NewEvent{}; - uint32_t NumEvents = LastEvent ? 1 : 0; - const ur_event_handle_t *EventsList = - LastEvent ? &LastEvent : nullptr; const char Pattern[] = {0}; auto URes = context.urDdiTable.Enqueue.pfnUSMFill( Queue, (void *)LaunchInfo.LocalShadowOffset, 1, Pattern, - LocalShadowMemorySize, NumEvents, EventsList, &NewEvent); + LocalShadowMemorySize, 0, nullptr, nullptr); if (URes != UR_RESULT_SUCCESS) { context.logger.error("urEnqueueUSMFill(): {}", URes); return URes; } - LastEvent = NewEvent; } context.logger.info("ShadowMemory(Local, {} - {})", @@ -885,7 +792,6 @@ ur_result_t SanitizerInterceptor::prepareLaunch(ur_queue_handle_t Queue, (void *)LaunchInfo.LocalShadowOffsetEnd); } while (false); - QueueInfo->LastEvent = LastEvent; return UR_RESULT_SUCCESS; } diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 484d14c8ee..48153aeade 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -15,6 +15,7 @@ #include "common.hpp" #include "device_sanitizer_report.hpp" #include "stacktrace.hpp" +#include "ur_sanitizer_layer.hpp" #include #include @@ -43,42 +44,89 @@ struct USMAllocInfo { StackTrace ReleaseStack; }; +struct USMAllocInfoList { + std::vector> List; + ur_shared_mutex Mutex; +}; + enum class DeviceType { UNKNOWN, CPU, GPU_PVC, GPU_DG2 }; struct DeviceInfo { + ur_device_handle_t Handle; + DeviceType Type; size_t Alignment; - uptr ShadowOffset; - uptr ShadowOffsetEnd; + uptr ShadowOffset = 0; + uptr ShadowOffsetEnd = 0; - // Lock InitPool & AllocInfos - ur_shared_mutex Mutex; - std::vector> AllocInfos; + DeviceInfo(ur_device_handle_t Device) : Handle(Device) { + [[maybe_unused]] auto Result = + context.urDdiTable.Device.pfnRetain(Device); + assert(Result == UR_RESULT_SUCCESS); + } + + ~DeviceInfo() { + [[maybe_unused]] auto Result = + context.urDdiTable.Device.pfnRelease(Handle); + assert(Result == UR_RESULT_SUCCESS); + } + + ur_result_t allocShadowMemory(ur_context_handle_t Context); }; struct QueueInfo { + ur_queue_handle_t Handle; ur_mutex Mutex; ur_event_handle_t LastEvent; + + QueueInfo(ur_queue_handle_t Queue) : Handle(Queue) { + [[maybe_unused]] auto Result = + context.urDdiTable.Queue.pfnRetain(Queue); + assert(Result == UR_RESULT_SUCCESS); + } + + ~QueueInfo() { + [[maybe_unused]] auto Result = + context.urDdiTable.Queue.pfnRelease(Handle); + assert(Result == UR_RESULT_SUCCESS); + } + + static std::unique_ptr Create(ur_context_handle_t Context, + ur_device_handle_t Device) { + ur_queue_handle_t Queue{}; + [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnCreate( + Context, Device, nullptr, &Queue); + assert(Result == UR_RESULT_SUCCESS); + return std::make_unique(Queue); + } }; struct ContextInfo { + ur_context_handle_t Handle; - std::shared_ptr getDeviceInfo(ur_device_handle_t Device) { - std::shared_lock Guard(Mutex); - assert(DeviceMap.find(Device) != DeviceMap.end()); - return DeviceMap[Device]; + std::vector DeviceList; + std::unordered_map AllocInfosMap; + + ContextInfo(ur_context_handle_t Context) : Handle(Context) { + [[maybe_unused]] auto Result = + context.urDdiTable.Context.pfnRetain(Context); + assert(Result == UR_RESULT_SUCCESS); } - std::shared_ptr getQueueInfo(ur_queue_handle_t Queue) { - std::shared_lock Guard(Mutex); - assert(QueueMap.find(Queue) != QueueMap.end()); - return QueueMap[Queue]; + ~ContextInfo() { + [[maybe_unused]] auto Result = + context.urDdiTable.Context.pfnRelease(Handle); + assert(Result == UR_RESULT_SUCCESS); } - ur_shared_mutex Mutex; - std::unordered_map> - DeviceMap; - std::unordered_map> QueueMap; + void insertAllocInfo(const std::vector &Devices, + std::shared_ptr &AllocInfo) { + for (auto Device : Devices) { + auto &AllocInfos = AllocInfosMap[Device]; + std::scoped_lock Guard(AllocInfos.Mutex); + AllocInfos.List.emplace_back(AllocInfo); + } + } }; struct LaunchInfo { @@ -95,6 +143,27 @@ struct LaunchInfo { ~LaunchInfo(); }; +struct ManagedQueue { + ManagedQueue(ur_context_handle_t Context, + ur_device_handle_t Device) { + [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnCreate( + Context, Device, nullptr, &Handle); + assert(Result == UR_RESULT_SUCCESS); + } + + ~ManagedQueue() { + [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnRelease(Handle); + assert(Result == UR_RESULT_SUCCESS); + } + + operator ur_queue_handle_t() { + return Handle; + } + +private: + ur_queue_handle_t Handle; +}; + class SanitizerInterceptor { public: SanitizerInterceptor(); @@ -109,17 +178,18 @@ class SanitizerInterceptor { ur_result_t releaseMemory(ur_context_handle_t Context, void *Ptr); ur_result_t preLaunchKernel(ur_kernel_handle_t Kernel, - ur_queue_handle_t Queue, - ur_event_handle_t &Event, - LaunchInfo &LaunchInfo, uint32_t numWorkgroup); + ur_queue_handle_t Queue, LaunchInfo &LaunchInfo, + uint32_t numWorkgroup); void postLaunchKernel(ur_kernel_handle_t Kernel, ur_queue_handle_t Queue, ur_event_handle_t &Event, LaunchInfo &LaunchInfo); - ur_result_t insertContext(ur_context_handle_t Context); + ur_result_t insertContext(ur_context_handle_t Context, + std::shared_ptr &CI); ur_result_t eraseContext(ur_context_handle_t Context); - ur_result_t insertDevice(ur_context_handle_t Context, - ur_device_handle_t Device); + ur_result_t insertDevice(ur_device_handle_t Device, + std::shared_ptr &CI); + ur_result_t eraseDevice(ur_device_handle_t Device); ur_result_t insertQueue(ur_context_handle_t Context, ur_queue_handle_t Queue); @@ -130,27 +200,30 @@ class SanitizerInterceptor { findAllocInfoByAddress(uptr Address, ur_context_handle_t Context, ur_device_handle_t Device); + ur_context_handle_t getPVCContext(); + private: - ur_result_t updateShadowMemory(ur_queue_handle_t Queue); + ur_result_t updateShadowMemory(std::shared_ptr &ContextInfo, + std::shared_ptr &DeviceInfo, + ur_queue_handle_t Queue); ur_result_t enqueueAllocInfo(ur_context_handle_t Context, - ur_device_handle_t Device, + std::shared_ptr &DeviceInfo, ur_queue_handle_t Queue, - std::shared_ptr &AlloccInfo, - ur_event_handle_t &LastEvent); + std::shared_ptr &AllocInfo); /// Initialize Global Variables & Kernel Name at first Launch - ur_result_t prepareLaunch(ur_queue_handle_t Queue, + ur_result_t prepareLaunch(ur_context_handle_t Context, + std::shared_ptr &DeviceInfo, + ur_queue_handle_t Queue, ur_kernel_handle_t Kernel, LaunchInfo &LaunchInfo, uint32_t numWorkgroup); ur_result_t allocShadowMemory(ur_context_handle_t Context, std::shared_ptr &DeviceInfo); ur_result_t enqueueMemSetShadow(ur_context_handle_t Context, - ur_device_handle_t Device, + std::shared_ptr &DeviceInfo, ur_queue_handle_t Queue, uptr Addr, - uptr Size, u8 Value, - ur_event_handle_t DepEvent, - ur_event_handle_t *OutEvent); + uptr Size, u8 Value); std::shared_ptr getContextInfo(ur_context_handle_t Context) { std::shared_lock Guard(m_ContextMapMutex); @@ -158,11 +231,21 @@ class SanitizerInterceptor { return m_ContextMap[Context]; } + std::shared_ptr getDeviceInfo(ur_device_handle_t Device) { + std::shared_lock Guard(m_DeviceMapMutex); + assert(m_DeviceMap.find(Device) != m_DeviceMap.end()); + return m_DeviceMap[Device]; + } + private: std::unordered_map> m_ContextMap; ur_shared_mutex m_ContextMapMutex; + std::unordered_map> + m_DeviceMap; + ur_shared_mutex m_DeviceMapMutex; + struct USMAllocInfoCompare { bool operator()(const std::shared_ptr &lhs, const std::shared_ptr &rhs) const { diff --git a/source/loader/layers/sanitizer/asan_shadow_setup.cpp b/source/loader/layers/sanitizer/asan_shadow_setup.cpp new file mode 100644 index 0000000000..3ff58b6bed --- /dev/null +++ b/source/loader/layers/sanitizer/asan_shadow_setup.cpp @@ -0,0 +1,137 @@ +/* + * + * Copyright (C) 2024 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file asan_shadow_setup.cpp + * + */ + +#include "asan_shadow_setup.hpp" +#include "ur_sanitizer_layer.hpp" + +namespace ur_sanitizer_layer { + +namespace cpu { + +// Based on "compiler-rt/lib/asan/asan_mapping.h" +// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: +constexpr uptr LOW_SHADOW_BEGIN = 0x00007fff8000ULL; +constexpr uptr LOW_SHADOW_END = 0x00008fff6fffULL; +constexpr uptr SHADOW_GAP_BEGIN = 0x00008fff7000ULL; +constexpr uptr SHADOW_GAP_END = 0x02008fff6fffULL; +constexpr uptr HIGH_SHADOW_BEGIN = 0x02008fff7000ULL; +constexpr uptr HIGH_SHADOW_END = 0x10007fff7fffULL; +constexpr uptr LOW_SHADOW_SIZE = LOW_SHADOW_END - LOW_SHADOW_BEGIN; +constexpr uptr SHADOW_GAP_SIZE = SHADOW_GAP_END - SHADOW_GAP_BEGIN; +constexpr uptr HIGH_SHADOW_SIZE = HIGH_SHADOW_END - HIGH_SHADOW_BEGIN; + +bool IsShadowMemInited; + +ur_result_t SetupShadowMemory(uptr &ShadowBegin, uptr &ShadowEnd) { + static ur_result_t Result = []() { + if (!MmapFixedNoReserve(LOW_SHADOW_BEGIN, LOW_SHADOW_SIZE)) { + return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + if (!MmapFixedNoReserve(HIGH_SHADOW_BEGIN, HIGH_SHADOW_SIZE)) { + return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + if (!MmapFixedNoAccess(SHADOW_GAP_BEGIN, SHADOW_GAP_SIZE)) { + return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + IsShadowMemInited = true; + return UR_RESULT_SUCCESS; + }(); + ShadowBegin = LOW_SHADOW_BEGIN; + ShadowEnd = HIGH_SHADOW_END; + return Result; +} + +ur_result_t DestroyShadowMemory() { + static ur_result_t Result = []() { + if (!IsShadowMemInited) { + return UR_RESULT_SUCCESS; + } + if (!Munmap(LOW_SHADOW_BEGIN, LOW_SHADOW_SIZE)) { + return UR_RESULT_ERROR_UNKNOWN; + } + if (!Munmap(HIGH_SHADOW_BEGIN, HIGH_SHADOW_SIZE)) { + return UR_RESULT_ERROR_UNKNOWN; + } + if (!Munmap(SHADOW_GAP_BEGIN, SHADOW_GAP_SIZE)) { + return UR_RESULT_ERROR_UNKNOWN; + } + return UR_RESULT_SUCCESS; + }(); + return Result; +} + +} // namespace cpu + +namespace pvc { + +/// SHADOW MEMORY MAPPING (PVC, with CPU 47bit) +/// Host/Shared USM : 0x0 ~ 0x0fff_ffff_ffff +/// ? : 0x1000_0000_0000 ~ 0x1fff_ffff_ffff +/// Device USM : 0x2000_0000_0000 ~ 0x3fff_ffff_ffff +constexpr size_t SHADOW_SIZE = 1ULL << 46; + +uptr LOW_SHADOW_BEGIN; +uptr HIGH_SHADOW_END; + +ur_context_handle_t ShadowContext; + +ur_result_t SetupShadowMemory(ur_context_handle_t Context, uptr &ShadowBegin, + uptr &ShadowEnd) { + // Currently, Level-Zero doesn't create independent VAs for each contexts, if we reserve + // shadow memory for each contexts, this will cause out-of-resource error when user uses + // multiple contexts. Therefore, we just create one shadow memory here. + static ur_result_t Result = [&Context]() { + // TODO: Protect Bad Zone + auto Result = context.urDdiTable.VirtualMem.pfnReserve( + Context, nullptr, SHADOW_SIZE, (void **)&LOW_SHADOW_BEGIN); + if (Result == UR_RESULT_SUCCESS) { + HIGH_SHADOW_END = LOW_SHADOW_BEGIN + SHADOW_SIZE; + // Retain the context which reserves shadow memory + ShadowContext = Context; + context.urDdiTable.Context.pfnRetain(Context); + } + return Result; + }(); + ShadowBegin = LOW_SHADOW_BEGIN; + ShadowEnd = HIGH_SHADOW_END; + return Result; +} + +ur_result_t DestroyShadowMemory() { + static ur_result_t Result = []() { + if (!ShadowContext) { + return UR_RESULT_SUCCESS; + } + auto Result = context.urDdiTable.VirtualMem.pfnFree( + ShadowContext, (const void *)LOW_SHADOW_BEGIN, SHADOW_SIZE); + context.urDdiTable.Context.pfnRelease(ShadowContext); + return Result; + }(); + return Result; +} + +} // namespace pvc + +ur_result_t SetupShadowMemoryOnCPU(uptr &ShadowBegin, uptr &ShadowEnd) { + return cpu::SetupShadowMemory(ShadowBegin, ShadowEnd); +} + +ur_result_t DestroyShadowMemoryOnCPU() { return cpu::DestroyShadowMemory(); } + +ur_result_t SetupShadowMemoryOnPVC(ur_context_handle_t Context, + uptr &ShadowBegin, uptr &ShadowEnd) { + return pvc::SetupShadowMemory(Context, ShadowBegin, ShadowEnd); +} + +ur_result_t DestroyShadowMemoryOnPVC() { return pvc::DestroyShadowMemory(); } + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_shadow_setup.hpp b/source/loader/layers/sanitizer/asan_shadow_setup.hpp new file mode 100644 index 0000000000..4b188d8831 --- /dev/null +++ b/source/loader/layers/sanitizer/asan_shadow_setup.hpp @@ -0,0 +1,26 @@ +/* + * + * Copyright (C) 2024 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file asan_shadow_setup.hpp + * + */ + +#pragma once + +#include "common.hpp" + +namespace ur_sanitizer_layer { + +ur_result_t SetupShadowMemoryOnCPU(uptr &ShadowBegin, uptr &ShadowEnd); +ur_result_t DestroyShadowMemoryOnCPU(); + +ur_result_t SetupShadowMemoryOnPVC(ur_context_handle_t Context, + uptr &ShadowBegin, uptr &ShadowEnd); +ur_result_t DestroyShadowMemoryOnPVC(); + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/common.hpp b/source/loader/layers/sanitizer/common.hpp index b9d39e95cb..f095b75623 100644 --- a/source/loader/layers/sanitizer/common.hpp +++ b/source/loader/layers/sanitizer/common.hpp @@ -30,18 +30,6 @@ using u32 = unsigned int; constexpr unsigned ASAN_SHADOW_SCALE = 3; constexpr unsigned ASAN_SHADOW_GRANULARITY = 1ULL << ASAN_SHADOW_SCALE; -// Based on "compiler-rt/lib/asan/asan_mapping.h" -// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: -constexpr uptr LOW_SHADOW_BEGIN = 0x00007fff8000ULL; -constexpr uptr LOW_SHADOW_END = 0x00008fff6fffULL; -constexpr uptr SHADOW_GAP_BEGIN = 0x00008fff7000ULL; -constexpr uptr SHADOW_GAP_END = 0x02008fff6fffULL; -constexpr uptr HIGH_SHADOW_BEGIN = 0x02008fff7000ULL; -constexpr uptr HIGH_SHADOW_END = 0x10007fff7fffULL; -constexpr uptr LOW_SHADOW_SIZE = LOW_SHADOW_END - LOW_SHADOW_BEGIN; -constexpr uptr SHADOW_GAP_SIZE = SHADOW_GAP_END - SHADOW_GAP_BEGIN; -constexpr uptr HIGH_SHADOW_SIZE = HIGH_SHADOW_END - HIGH_SHADOW_BEGIN; - inline constexpr bool IsPowerOfTwo(uptr x) { return (x & (x - 1)) == 0 && x != 0; } @@ -105,9 +93,9 @@ struct AddressInfo { bool IsInASanContext(); -bool SetupShadowMem(); - -bool DestroyShadowMem(); +bool MmapFixedNoReserve(uptr Addr, uptr Size); +bool MmapFixedNoAccess(uptr Addr, uptr Size); +bool Munmap(uptr Addr, uptr Size); void *GetMemFunctionPointer(const char *); diff --git a/source/loader/layers/sanitizer/linux/san_utils.cpp b/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp similarity index 62% rename from source/loader/layers/sanitizer/linux/san_utils.cpp rename to source/loader/layers/sanitizer/linux/sanitizer_utils.cpp index fa28d0a9d2..14bdf9403e 100644 --- a/source/loader/layers/sanitizer/linux/san_utils.cpp +++ b/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp @@ -7,7 +7,7 @@ * See LICENSE.TXT * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception * - * @file san_utils.cpp + * @file sanitizer_utils.cpp * */ @@ -24,7 +24,7 @@ namespace ur_sanitizer_layer { bool IsInASanContext() { return __asan_init != nullptr; } -static bool ReserveShadowMem(uptr Addr, uptr Size) { +bool MmapFixedNoReserve(uptr Addr, uptr Size) { Size = RoundUpTo(Size, EXEC_PAGESIZE); Addr = RoundDownTo(Addr, EXEC_PAGESIZE); void *P = @@ -33,42 +33,14 @@ static bool ReserveShadowMem(uptr Addr, uptr Size) { return Addr == (uptr)P; } -static bool ProtectShadowGap(uptr Addr, uptr Size) { +bool MmapFixedNoAccess(uptr Addr, uptr Size) { void *P = mmap((void *)Addr, Size, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANONYMOUS, -1, 0); return Addr == (uptr)P; } -bool SetupShadowMem() { - if (!ReserveShadowMem(LOW_SHADOW_BEGIN, LOW_SHADOW_SIZE)) { - return false; - } - - if (!ReserveShadowMem(HIGH_SHADOW_BEGIN, HIGH_SHADOW_SIZE)) { - return false; - } - - if (!ProtectShadowGap(SHADOW_GAP_BEGIN, SHADOW_GAP_SIZE)) { - return false; - } - return true; -} - -bool DestroyShadowMem() { - if (munmap((void *)LOW_SHADOW_BEGIN, LOW_SHADOW_SIZE) == -1) { - return false; - } - - if (munmap((void *)HIGH_SHADOW_BEGIN, HIGH_SHADOW_SIZE) == -1) { - return false; - } - - if (munmap((void *)SHADOW_GAP_BEGIN, SHADOW_GAP_SIZE) == -1) { - return false; - } - return true; -} +bool Munmap(uptr Addr, uptr Size) { return munmap((void *)Addr, Size) == 0; } void *GetMemFunctionPointer(const char *FuncName) { void *handle = dlopen(LIBC_SO, RTLD_LAZY); diff --git a/source/loader/layers/sanitizer/stacktrace.hpp b/source/loader/layers/sanitizer/stacktrace.hpp index 046b3e46b0..e0225b4723 100644 --- a/source/loader/layers/sanitizer/stacktrace.hpp +++ b/source/loader/layers/sanitizer/stacktrace.hpp @@ -14,7 +14,6 @@ #include "common.hpp" -#include #include namespace ur_sanitizer_layer { @@ -29,4 +28,4 @@ struct StackTrace { StackTrace GetCurrentBacktrace(); -} // namespace ur_sanitizer_layer \ No newline at end of file +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index 13da364ee6..9aa18536a8 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -15,6 +15,27 @@ namespace ur_sanitizer_layer { +namespace { + +ur_result_t setupContext(ur_context_handle_t Context, uint32_t numDevices, + const ur_device_handle_t *phDevices) { + std::shared_ptr CI; + UR_CALL(context.interceptor->insertContext(Context, CI)); + for (uint32_t i = 0; i < numDevices; ++i) { + auto hDevice = phDevices[i]; + std::shared_ptr DI; + UR_CALL(context.interceptor->insertDevice(hDevice, DI)); + if (!DI->ShadowOffset) { + UR_CALL(DI->allocShadowMemory(Context)); + } + CI->DeviceList.emplace_back(std::move(DI)); + CI->AllocInfosMap.emplace(hDevice, USMAllocInfoList{}); + } + return UR_RESULT_SUCCESS; +} + +} // namespace + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urUSMHostAlloc __urdlllocal ur_result_t UR_APICALL urUSMHostAlloc( @@ -106,56 +127,6 @@ __urdlllocal ur_result_t UR_APICALL urUSMFree( return context.interceptor->releaseMemory(hContext, pMem); } -/////////////////////////////////////////////////////////////////////////////// -/// @brief Intercept function for urQueueCreate -__urdlllocal ur_result_t UR_APICALL urQueueCreate( - ur_context_handle_t hContext, ///< [in] handle of the context object - ur_device_handle_t hDevice, ///< [in] handle of the device object - const ur_queue_properties_t - *pProperties, ///< [in][optional] pointer to queue creation properties. - ur_queue_handle_t - *phQueue ///< [out] pointer to handle of queue object created -) { - auto pfnCreate = context.urDdiTable.Queue.pfnCreate; - - if (nullptr == pfnCreate) { - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; - } - - context.logger.debug("==== urQueueCreate"); - - ur_result_t result = pfnCreate(hContext, hDevice, pProperties, phQueue); - if (result == UR_RESULT_SUCCESS) { - result = context.interceptor->insertQueue(hContext, *phQueue); - } - - return result; -} - -/////////////////////////////////////////////////////////////////////////////// -/// @brief Intercept function for urQueueRelease -__urdlllocal ur_result_t UR_APICALL urQueueRelease( - ur_queue_handle_t hQueue ///< [in] handle of the queue object to release -) { - auto pfnRelease = context.urDdiTable.Queue.pfnRelease; - - if (nullptr == pfnRelease) { - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; - } - - context.logger.debug("==== urQueueRelease"); - - ur_context_handle_t hContext; - UR_CALL(context.urDdiTable.Queue.pfnGetInfo(hQueue, UR_QUEUE_INFO_CONTEXT, - sizeof(ur_context_handle_t), - &hContext, nullptr)); - UR_CALL(context.interceptor->eraseQueue(hContext, hQueue)); - - ur_result_t result = pfnRelease(hQueue); - - return result; -} - /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urEnqueueKernelLaunch __urdlllocal ur_result_t UR_APICALL urEnqueueKernelLaunch( @@ -211,18 +182,8 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueKernelLaunch( pUserLocalWorkSize[dim]; } - std::vector hEvents; - for (uint32_t i = 0; i < numEventsInWaitList; ++i) { - hEvents.push_back(phEventWaitList[i]); - } - - // preLaunchKernel must append to num_events_in_wait_list, not prepend - ur_event_handle_t hPreEvent{}; - UR_CALL(context.interceptor->preLaunchKernel(hKernel, hQueue, hPreEvent, - LaunchInfo, numWork)); - if (hPreEvent) { - hEvents.push_back(hPreEvent); - } + UR_CALL(context.interceptor->preLaunchKernel(hKernel, hQueue, LaunchInfo, + numWork)); ur_event_handle_t hEvent{}; ur_result_t result = pfnKernelLaunch( @@ -264,17 +225,7 @@ __urdlllocal ur_result_t UR_APICALL urContextCreate( pfnCreate(numDevices, phDevices, pProperties, phContext); if (result == UR_RESULT_SUCCESS) { - auto Context = *phContext; - result = context.interceptor->insertContext(Context); - if (result != UR_RESULT_SUCCESS) { - return result; - } - for (uint32_t i = 0; i < numDevices; ++i) { - result = context.interceptor->insertDevice(Context, phDevices[i]); - if (result != UR_RESULT_SUCCESS) { - return result; - } - } + UR_CALL(setupContext(*phContext, numDevices, phDevices)); } return result; @@ -306,17 +257,7 @@ __urdlllocal ur_result_t UR_APICALL urContextCreateWithNativeHandle( hNativeContext, numDevices, phDevices, pProperties, phContext); if (result == UR_RESULT_SUCCESS) { - auto Context = *phContext; - result = context.interceptor->insertContext(Context); - if (result != UR_RESULT_SUCCESS) { - return result; - } - for (uint32_t i = 0; i < numDevices; ++i) { - result = context.interceptor->insertDevice(Context, phDevices[i]); - if (result != UR_RESULT_SUCCESS) { - return result; - } - } + UR_CALL(setupContext(*phContext, numDevices, phDevices)); } return result; @@ -341,6 +282,8 @@ __urdlllocal ur_result_t UR_APICALL urContextRelease( return result; } +// TODO: urDeviceRelease + /////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's Context table /// with current process' addresses @@ -406,37 +349,6 @@ __urdlllocal ur_result_t UR_APICALL urGetEnqueueProcAddrTable( return result; } /////////////////////////////////////////////////////////////////////////////// -/// @brief Exported function for filling application's Queue table -/// with current process' addresses -/// -/// @returns -/// - ::UR_RESULT_SUCCESS -/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER -/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION -__urdlllocal ur_result_t UR_APICALL urGetQueueProcAddrTable( - ur_api_version_t version, ///< [in] API version requested - ur_queue_dditable_t - *pDdiTable ///< [in,out] pointer to table of DDI function pointers -) { - if (nullptr == pDdiTable) { - return UR_RESULT_ERROR_INVALID_NULL_POINTER; - } - - if (UR_MAJOR_VERSION(ur_sanitizer_layer::context.version) != - UR_MAJOR_VERSION(version) || - UR_MINOR_VERSION(ur_sanitizer_layer::context.version) > - UR_MINOR_VERSION(version)) { - return UR_RESULT_ERROR_UNSUPPORTED_VERSION; - } - - ur_result_t result = UR_RESULT_SUCCESS; - - pDdiTable->pfnCreate = ur_sanitizer_layer::urQueueCreate; - pDdiTable->pfnRelease = ur_sanitizer_layer::urQueueRelease; - - return result; -} -/////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's USM table /// with current process' addresses /// @@ -511,11 +423,6 @@ ur_result_t context_t::init(ur_dditable_t *dditable, UR_API_VERSION_CURRENT, &dditable->Enqueue); } - if (UR_RESULT_SUCCESS == result) { - result = ur_sanitizer_layer::urGetQueueProcAddrTable( - UR_API_VERSION_CURRENT, &dditable->Queue); - } - if (UR_RESULT_SUCCESS == result) { result = ur_sanitizer_layer::urGetUSMProcAddrTable( UR_API_VERSION_CURRENT, &dditable->USM); @@ -523,4 +430,5 @@ ur_result_t context_t::init(ur_dditable_t *dditable, return result; } + } // namespace ur_sanitizer_layer From 090dbcae8c439ea0934f1bd4a69b82b39388617e Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 20 Feb 2024 00:19:28 -0800 Subject: [PATCH 09/42] fix build --- source/loader/layers/sanitizer/ur_sanddi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index 9aa18536a8..30eadf3dc1 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -28,8 +28,8 @@ ur_result_t setupContext(ur_context_handle_t Context, uint32_t numDevices, if (!DI->ShadowOffset) { UR_CALL(DI->allocShadowMemory(Context)); } - CI->DeviceList.emplace_back(std::move(DI)); - CI->AllocInfosMap.emplace(hDevice, USMAllocInfoList{}); + CI->DeviceList.emplace_back(hDevice); + CI->AllocInfosMap[hDevice]; } return UR_RESULT_SUCCESS; } From 010b052b92cb8f1fe697abb2a0c95ba37d5c6cb7 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 20 Feb 2024 00:45:38 -0800 Subject: [PATCH 10/42] fix crash --- source/loader/layers/sanitizer/asan_interceptor.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 36f0f9fe2b..191892c8d7 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -661,7 +661,7 @@ SanitizerInterceptor::insertContext(ur_context_handle_t Context, CI = std::make_shared(Context); - m_ContextMap.emplace(Context, std::move(CI)); + m_ContextMap.emplace(Context, CI); return UR_RESULT_SUCCESS; } @@ -697,7 +697,7 @@ SanitizerInterceptor::insertDevice(ur_device_handle_t Device, Device, UR_DEVICE_INFO_MEM_BASE_ADDR_ALIGN, sizeof(DI->Alignment), &DI->Alignment, nullptr)); - m_DeviceMap.emplace(Device, std::move(DI)); + m_DeviceMap.emplace(Device, DI); return UR_RESULT_SUCCESS; } @@ -718,7 +718,8 @@ ur_result_t SanitizerInterceptor::prepareLaunch( do { // Set global variable to program - auto EnqueueWriteGlobal = [&](const char *Name, const void *Value) { + auto EnqueueWriteGlobal = [&Queue, &Program](const char *Name, + const void *Value) { auto Result = context.urDdiTable.Enqueue.pfnDeviceGlobalVariableWrite( Queue, Program, Name, false, sizeof(uptr), 0, Value, 0, From 024e8657d03ff8f796d10a23821e2847a039697f Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Thu, 22 Feb 2024 21:24:51 -0800 Subject: [PATCH 11/42] small fix --- .../layers/sanitizer/asan_interceptor.cpp | 28 ++++++++++--------- .../layers/sanitizer/asan_interceptor.hpp | 22 ++++++--------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 191892c8d7..e914cdab56 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -15,7 +15,6 @@ #include "asan_shadow_setup.hpp" #include "device_sanitizer_report.hpp" #include "stacktrace.hpp" -#include "ur_api.h" namespace ur_sanitizer_layer { @@ -60,7 +59,7 @@ uptr MemToShadow_PVC(uptr USM_SHADOW_BASE, uptr UPtr) { } ur_context_handle_t getContext(ur_queue_handle_t Queue) { - ur_context_handle_t Context; + ur_context_handle_t Context{}; [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( Queue, UR_QUEUE_INFO_CONTEXT, sizeof(ur_context_handle_t), &Context, nullptr); @@ -69,7 +68,7 @@ ur_context_handle_t getContext(ur_queue_handle_t Queue) { } ur_device_handle_t getDevice(ur_queue_handle_t Queue) { - ur_device_handle_t Device; + ur_device_handle_t Device{}; [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( Queue, UR_QUEUE_INFO_DEVICE, sizeof(ur_device_handle_t), &Device, nullptr); @@ -78,7 +77,7 @@ ur_device_handle_t getDevice(ur_queue_handle_t Queue) { } ur_program_handle_t getProgram(ur_kernel_handle_t Kernel) { - ur_program_handle_t Program; + ur_program_handle_t Program{}; [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( Kernel, UR_KERNEL_INFO_PROGRAM, sizeof(ur_program_handle_t), &Program, nullptr); @@ -87,7 +86,7 @@ ur_program_handle_t getProgram(ur_kernel_handle_t Kernel) { } size_t getLocalMemorySize(ur_device_handle_t Device) { - size_t LocalMemorySize; + size_t LocalMemorySize{}; [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( Device, UR_DEVICE_INFO_LOCAL_MEM_SIZE, sizeof(LocalMemorySize), &LocalMemorySize, nullptr); @@ -112,16 +111,16 @@ std::string getKernelName(ur_kernel_handle_t Kernel) { ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, const void *MemPtr) { - ur_device_handle_t Device; - [[maybe_unused]] auto Result = context.urDdiTable.USM.pfnGetMemAllocInfo( - Context, MemPtr, UR_USM_ALLOC_INFO_DEVICE, sizeof(Device), &Device, - nullptr); - assert(Result == UR_RESULT_SUCCESS && "getUSMAllocDevice() failed"); + ur_device_handle_t Device{}; + // if urGetMemAllocInfo failed, return nullptr + context.urDdiTable.USM.pfnGetMemAllocInfo(Context, MemPtr, + UR_USM_ALLOC_INFO_DEVICE, + sizeof(Device), &Device, nullptr); return Device; } DeviceType getDeviceType(ur_device_handle_t Device) { - ur_device_type_t DeviceType; + ur_device_type_t DeviceType = UR_DEVICE_TYPE_DEFAULT; [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( Device, UR_DEVICE_INFO_TYPE, sizeof(DeviceType), &DeviceType, nullptr); assert(Result == UR_RESULT_SUCCESS && "getDeviceType() failed"); @@ -129,7 +128,7 @@ DeviceType getDeviceType(ur_device_handle_t Device) { case UR_DEVICE_TYPE_CPU: return DeviceType::CPU; case UR_DEVICE_TYPE_GPU: { - // TODO: Check device vendor + // TODO: Check device name return DeviceType::GPU_PVC; } default: @@ -394,6 +393,9 @@ ur_result_t SanitizerInterceptor::preLaunchKernel(ur_kernel_handle_t Kernel, auto DeviceInfo = getDeviceInfo(Device); ManagedQueue InternalQueue(Context, Device); + if (!InternalQueue) { + return UR_RESULT_ERROR_INVALID_QUEUE; + } UR_CALL(prepareLaunch(Context, DeviceInfo, InternalQueue, Kernel, LaunchInfo, numWorkgroup)); @@ -473,7 +475,7 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( MemToShadow_PVC(DeviceInfo->ShadowOffset, Ptr + Size - 1); { - static const size_t PageSize = [Context, DeviceInfo]() { + static const size_t PageSize = [Context, &DeviceInfo]() { size_t Size; [[maybe_unused]] auto Result = context.urDdiTable.VirtualMem.pfnGranularityGetInfo( diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 48153aeade..3f7cbbeb5c 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -54,8 +54,8 @@ enum class DeviceType { UNKNOWN, CPU, GPU_PVC, GPU_DG2 }; struct DeviceInfo { ur_device_handle_t Handle; - DeviceType Type; - size_t Alignment; + DeviceType Type = DeviceType::UNKNOWN; + size_t Alignment = 0; uptr ShadowOffset = 0; uptr ShadowOffsetEnd = 0; @@ -79,7 +79,7 @@ struct QueueInfo { ur_mutex Mutex; ur_event_handle_t LastEvent; - QueueInfo(ur_queue_handle_t Queue) : Handle(Queue) { + QueueInfo(ur_queue_handle_t Queue) : Handle(Queue), LastEvent(nullptr) { [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnRetain(Queue); assert(Result == UR_RESULT_SUCCESS); @@ -144,24 +144,22 @@ struct LaunchInfo { }; struct ManagedQueue { - ManagedQueue(ur_context_handle_t Context, - ur_device_handle_t Device) { + ManagedQueue(ur_context_handle_t Context, ur_device_handle_t Device) { [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnCreate( Context, Device, nullptr, &Handle); assert(Result == UR_RESULT_SUCCESS); } ~ManagedQueue() { - [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnRelease(Handle); + [[maybe_unused]] auto Result = + context.urDdiTable.Queue.pfnRelease(Handle); assert(Result == UR_RESULT_SUCCESS); } - operator ur_queue_handle_t() { - return Handle; - } + operator ur_queue_handle_t() { return Handle; } -private: - ur_queue_handle_t Handle; + private: + ur_queue_handle_t Handle = nullptr; }; class SanitizerInterceptor { @@ -200,8 +198,6 @@ class SanitizerInterceptor { findAllocInfoByAddress(uptr Address, ur_context_handle_t Context, ur_device_handle_t Device); - ur_context_handle_t getPVCContext(); - private: ur_result_t updateShadowMemory(std::shared_ptr &ContextInfo, std::shared_ptr &DeviceInfo, From 7d2b5e9106ef4370d26f7dc4acf4e945e161ce46 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Thu, 22 Feb 2024 22:17:39 -0800 Subject: [PATCH 12/42] fix size of DeviceType --- .../layers/sanitizer/asan_interceptor.cpp | 41 +++++++++++-------- .../layers/sanitizer/asan_interceptor.hpp | 2 +- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index e914cdab56..c520280999 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -720,28 +720,31 @@ ur_result_t SanitizerInterceptor::prepareLaunch( do { // Set global variable to program - auto EnqueueWriteGlobal = [&Queue, &Program](const char *Name, - const void *Value) { - auto Result = - context.urDdiTable.Enqueue.pfnDeviceGlobalVariableWrite( - Queue, Program, Name, false, sizeof(uptr), 0, Value, 0, - nullptr, nullptr); - if (Result != UR_RESULT_SUCCESS) { - context.logger.warning("Device Global[{}] Write Failed: {}", - Name, Result); - return false; - } - return true; - }; + auto EnqueueWriteGlobal = + [Queue, Program](const char *Name, const void *Value, size_t Size) { + auto Result = + context.urDdiTable.Enqueue.pfnDeviceGlobalVariableWrite( + Queue, Program, Name, false, Size, 0, Value, 0, nullptr, + nullptr); + if (Result != UR_RESULT_SUCCESS) { + context.logger.warning("Device Global[{}] Write Failed: {}", + Name, Result); + return false; + } + return true; + }; // Write shadow memory offset for global memory EnqueueWriteGlobal(kSPIR_AsanShadowMemoryGlobalStart, - &DeviceInfo->ShadowOffset); + &DeviceInfo->ShadowOffset, + sizeof(DeviceInfo->ShadowOffset)); EnqueueWriteGlobal(kSPIR_AsanShadowMemoryGlobalEnd, - &DeviceInfo->ShadowOffsetEnd); + &DeviceInfo->ShadowOffsetEnd, + sizeof(DeviceInfo->ShadowOffsetEnd)); // Write device type - EnqueueWriteGlobal(kSPIR_DeviceType, &DeviceInfo->Type); + EnqueueWriteGlobal(kSPIR_DeviceType, &DeviceInfo->Type, + sizeof(DeviceInfo->Type)); if (DeviceInfo->Type == DeviceType::CPU) { break; @@ -772,9 +775,11 @@ ur_result_t SanitizerInterceptor::prepareLaunch( LaunchInfo.LocalShadowOffset + LocalShadowMemorySize - 1; EnqueueWriteGlobal(kSPIR_AsanShadowMemoryLocalStart, - &LaunchInfo.LocalShadowOffset); + &LaunchInfo.LocalShadowOffset, + sizeof(LaunchInfo.LocalShadowOffset)); EnqueueWriteGlobal(kSPIR_AsanShadowMemoryLocalEnd, - &LaunchInfo.LocalShadowOffsetEnd); + &LaunchInfo.LocalShadowOffsetEnd, + sizeof(LaunchInfo.LocalShadowOffsetEnd)); { const char Pattern[] = {0}; diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 3f7cbbeb5c..4e21d0fd41 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -49,7 +49,7 @@ struct USMAllocInfoList { ur_shared_mutex Mutex; }; -enum class DeviceType { UNKNOWN, CPU, GPU_PVC, GPU_DG2 }; +enum class DeviceType : uint32_t { UNKNOWN = 0, CPU, GPU_PVC, GPU_DG2 }; struct DeviceInfo { ur_device_handle_t Handle; From a058dbf0043ffb7c36ae4ba88f913ec1a66464d5 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Mon, 26 Feb 2024 23:50:41 -0800 Subject: [PATCH 13/42] WIP --- .../layers/sanitizer/asan_allocator.cpp | 34 +++ .../layers/sanitizer/asan_allocator.hpp | 40 +++ .../layers/sanitizer/asan_interceptor.cpp | 257 +++++------------- .../layers/sanitizer/asan_interceptor.hpp | 58 +--- .../layers/sanitizer/asan_quarantine.cpp | 29 ++ .../layers/sanitizer/asan_quarantine.hpp | 74 +++++ .../loader/layers/sanitizer/asan_report.cpp | 102 +++++++ .../loader/layers/sanitizer/asan_report.hpp | 34 +++ source/loader/layers/sanitizer/common.hpp | 2 + source/loader/layers/sanitizer/stacktrace.hpp | 2 +- .../layers/sanitizer/ur_sanitizer_utils.cpp | 96 +++++++ .../layers/sanitizer/ur_sanitizer_utils.hpp | 28 ++ 12 files changed, 522 insertions(+), 234 deletions(-) create mode 100644 source/loader/layers/sanitizer/asan_allocator.cpp create mode 100644 source/loader/layers/sanitizer/asan_allocator.hpp create mode 100644 source/loader/layers/sanitizer/asan_quarantine.cpp create mode 100644 source/loader/layers/sanitizer/asan_quarantine.hpp create mode 100644 source/loader/layers/sanitizer/asan_report.cpp create mode 100644 source/loader/layers/sanitizer/asan_report.hpp create mode 100644 source/loader/layers/sanitizer/ur_sanitizer_utils.cpp create mode 100644 source/loader/layers/sanitizer/ur_sanitizer_utils.hpp diff --git a/source/loader/layers/sanitizer/asan_allocator.cpp b/source/loader/layers/sanitizer/asan_allocator.cpp new file mode 100644 index 0000000000..c0895a698e --- /dev/null +++ b/source/loader/layers/sanitizer/asan_allocator.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (C) 2024 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file asan_allocator.cpp + * + */ + +#pragma once + +#include "asan_allocator.hpp" + +namespace ur_sanitizer_layer { + +const char *getFormatString(MemoryType MemoryType) { + switch (MemoryType) { + case MemoryType::DEVICE_USM: + return "USM Device Memory"; + case MemoryType::HOST_USM: + return "USM Host Memory"; + case MemoryType::SHARED_USM: + return "USM Shared Memory"; + case MemoryType::MEM_BUFFER: + return "Memory Buffer"; + default: + return "Unknown Memory"; + } +} + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_allocator.hpp b/source/loader/layers/sanitizer/asan_allocator.hpp new file mode 100644 index 0000000000..e4b3d94884 --- /dev/null +++ b/source/loader/layers/sanitizer/asan_allocator.hpp @@ -0,0 +1,40 @@ +/* + * + * Copyright (C) 2024 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file asan_allocator.hpp + * + */ + +#pragma once + +#include "common.hpp" +#include "stacktrace.hpp" + +namespace ur_sanitizer_layer { + +enum MemoryType { DEVICE_USM, SHARED_USM, HOST_USM, MEM_BUFFER }; + +struct USMAllocInfo { + uptr AllocBegin = 0; + uptr UserBegin = 0; + uptr UserEnd = 0; + size_t AllocSize = 0; + + MemoryType Type = MemoryType::DEVICE_USM; + bool IsReleased = false; + + ur_context_handle_t Context = nullptr; + ur_device_handle_t Device = nullptr; + + StackTrace AllocStack; + StackTrace ReleaseStack; +}; + +const char *getFormatString(MemoryType MemoryType); + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index c520280999..ef530e0f63 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -12,9 +12,12 @@ */ #include "asan_interceptor.hpp" +#include "asan_quarantine.hpp" +#include "asan_report.hpp" #include "asan_shadow_setup.hpp" #include "device_sanitizer_report.hpp" #include "stacktrace.hpp" +#include "ur_sanitizer_utils.hpp" namespace ur_sanitizer_layer { @@ -40,10 +43,28 @@ constexpr auto kSPIR_AsanShadowMemoryLocalStart = constexpr auto kSPIR_AsanShadowMemoryLocalEnd = "__AsanShadowMemoryLocalEnd"; constexpr auto kSPIR_DeviceType = "__DeviceType"; +constexpr auto kSPIR_AsanDebug = "__AsanDebug"; constexpr auto kSPIR_DeviceSanitizerReportMem = "__DeviceSanitizerReportMem"; -DeviceSanitizerReport SPIR_DeviceSanitizerReportMem; +struct ManagedQueue { + ManagedQueue(ur_context_handle_t Context, ur_device_handle_t Device) { + [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnCreate( + Context, Device, nullptr, &Handle); + assert(Result == UR_RESULT_SUCCESS); + } + + ~ManagedQueue() { + [[maybe_unused]] auto Result = + context.urDdiTable.Queue.pfnRelease(Handle); + assert(Result == UR_RESULT_SUCCESS); + } + + operator ur_queue_handle_t() { return Handle; } + + private: + ur_queue_handle_t Handle = nullptr; +}; uptr MemToShadow_CPU(uptr USM_SHADOW_BASE, uptr UPtr) { return USM_SHADOW_BASE + (UPtr >> 3); @@ -58,184 +79,27 @@ uptr MemToShadow_PVC(uptr USM_SHADOW_BASE, uptr UPtr) { } } -ur_context_handle_t getContext(ur_queue_handle_t Queue) { - ur_context_handle_t Context{}; - [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( - Queue, UR_QUEUE_INFO_CONTEXT, sizeof(ur_context_handle_t), &Context, - nullptr); - assert(Result == UR_RESULT_SUCCESS && "getContext() failed"); - return Context; -} - -ur_device_handle_t getDevice(ur_queue_handle_t Queue) { - ur_device_handle_t Device{}; - [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( - Queue, UR_QUEUE_INFO_DEVICE, sizeof(ur_device_handle_t), &Device, - nullptr); - assert(Result == UR_RESULT_SUCCESS && "getDevice() failed"); - return Device; -} - -ur_program_handle_t getProgram(ur_kernel_handle_t Kernel) { - ur_program_handle_t Program{}; - [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( - Kernel, UR_KERNEL_INFO_PROGRAM, sizeof(ur_program_handle_t), &Program, - nullptr); - assert(Result == UR_RESULT_SUCCESS && "getProgram() failed"); - return Program; -} - -size_t getLocalMemorySize(ur_device_handle_t Device) { - size_t LocalMemorySize{}; - [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( - Device, UR_DEVICE_INFO_LOCAL_MEM_SIZE, sizeof(LocalMemorySize), - &LocalMemorySize, nullptr); - assert(Result == UR_RESULT_SUCCESS && "getLocalMemorySize() failed"); - return LocalMemorySize; -} - -std::string getKernelName(ur_kernel_handle_t Kernel) { - size_t KernelNameSize = 0; - [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( - Kernel, UR_KERNEL_INFO_FUNCTION_NAME, 0, nullptr, &KernelNameSize); - assert(Result == UR_RESULT_SUCCESS && "getKernelName() failed"); - - std::vector KernelNameBuf(KernelNameSize); - Result = context.urDdiTable.Kernel.pfnGetInfo( - Kernel, UR_KERNEL_INFO_FUNCTION_NAME, KernelNameSize, - KernelNameBuf.data(), nullptr); - assert(Result == UR_RESULT_SUCCESS && "getKernelName() failed"); - - return std::string(KernelNameBuf.data(), KernelNameSize - 1); -} - -ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, - const void *MemPtr) { - ur_device_handle_t Device{}; - // if urGetMemAllocInfo failed, return nullptr - context.urDdiTable.USM.pfnGetMemAllocInfo(Context, MemPtr, - UR_USM_ALLOC_INFO_DEVICE, - sizeof(Device), &Device, nullptr); - return Device; -} - -DeviceType getDeviceType(ur_device_handle_t Device) { - ur_device_type_t DeviceType = UR_DEVICE_TYPE_DEFAULT; - [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( - Device, UR_DEVICE_INFO_TYPE, sizeof(DeviceType), &DeviceType, nullptr); - assert(Result == UR_RESULT_SUCCESS && "getDeviceType() failed"); - switch (DeviceType) { - case UR_DEVICE_TYPE_CPU: - return DeviceType::CPU; - case UR_DEVICE_TYPE_GPU: { - // TODO: Check device name - return DeviceType::GPU_PVC; - } - default: - return DeviceType::UNKNOWN; - } -} +} // namespace -const char *getFormatString(MemoryType MemoryType) { - switch (MemoryType) { - case MemoryType::DEVICE_USM: - return "USM Device Memory"; - case MemoryType::HOST_USM: - return "USM Host Memory"; - case MemoryType::SHARED_USM: - return "USM Shared Memory"; - case MemoryType::MEM_BUFFER: - return "Memory Buffer"; - default: - return "Unknown Memory"; +SanitizerInterceptor::SanitizerInterceptor() { + auto Options = getenv_to_map("UR_LAYER_ASAN_OPTIONS"); + auto KV = Options->find("debug"); + if (KV != Options->end()) { + auto Value = KV->second.front(); + if (Value == "1" || Value == "true") { + cl_Debug = 1; + } } -} - -void ReportBadFree(uptr Addr, StackTrace stack, - std::shared_ptr AllocInfo) { - context.logger.always( - "\n====ERROR: DeviceSanitizer: attempting free on address which " - "was not malloc()-ed: {} in thread T0", - (void *)Addr); - stack.Print(); - - if (!AllocInfo) { // maybe Addr is host allocated memory - context.logger.always("{} is maybe allocated on Host Memory", - (void *)Addr); - exit(1); + KV = Options->find("quarantine_size_mb"); + if (KV != Options->end()) { + auto Value = KV->second.front(); + cl_MaxQuarantineSizeMB = std::stoul(Value); } - - assert(!AllocInfo->IsReleased && "Chunk must be not released"); - - context.logger.always("{} is located inside of {} region [{}, {}]", - (void *)Addr, getFormatString(AllocInfo->Type), - (void *)AllocInfo->UserBegin, - (void *)AllocInfo->UserEnd); - context.logger.always("allocated by thread T0 here:"); - AllocInfo->AllocStack.Print(); - - exit(1); -} - -void ReportDoubleFree(uptr Addr, StackTrace Stack, - std::shared_ptr AllocInfo) { - context.logger.always("\n====ERROR: DeviceSanitizer: double-free on {}", - (void *)Addr); - Stack.Print(); - AllocInfo->AllocStack.Print(); - AllocInfo->ReleaseStack.Print(); - exit(1); -} - -void ReportGenericError(DeviceSanitizerReport &Report, - ur_kernel_handle_t Kernel, ur_context_handle_t Context, - ur_device_handle_t Device) { - const char *File = Report.File[0] ? Report.File : ""; - const char *Func = Report.Func[0] ? Report.Func : ""; - auto KernelName = getKernelName(Kernel); - - context.logger.always("\n====ERROR: DeviceSanitizer: {} on {}", - DeviceSanitizerFormat(Report.ErrorType), - DeviceSanitizerFormat(Report.MemoryType)); - context.logger.always( - "{} of size {} at kernel <{}> LID({}, {}, {}) GID({}, " - "{}, {})", - Report.IsWrite ? "WRITE" : "READ", Report.AccessSize, - KernelName.c_str(), Report.LID0, Report.LID1, Report.LID2, Report.GID0, - Report.GID1, Report.GID2); - context.logger.always(" #0 {} {}:{}\n", Func, File, Report.Line); - - if (Report.ErrorType == DeviceSanitizerErrorType::USE_AFTER_FREE) { - auto AllocInfos = context.interceptor->findAllocInfoByAddress( - Report.Addr, Context, Device); - if (!AllocInfos.size()) { - context.logger.always("can't find which chunck {} is allocated", - (void *)Report.Addr); - } - for (auto &AllocInfo : AllocInfos) { - if (!AllocInfo->IsReleased) { - continue; - } - context.logger.always( - "{} is located inside of {} region [{}, {}]", - (void *)Report.Addr, getFormatString(AllocInfo->Type), - (void *)AllocInfo->UserBegin, (void *)AllocInfo->UserEnd); - context.logger.always("allocated by thread T0 here:"); - AllocInfo->AllocStack.Print(); - context.logger.always("released by thread T0 here:"); - AllocInfo->ReleaseStack.Print(); - } + if (cl_MaxQuarantineSizeMB) { + m_Quarantine = std::make_unique(cl_MaxQuarantineSizeMB); } - - exit(1); } -} // namespace - -SanitizerInterceptor::SanitizerInterceptor() - : m_IsInASanContext(IsInASanContext()), - m_ShadowMemInited(m_IsInASanContext) {} - SanitizerInterceptor::~SanitizerInterceptor() { DestroyShadowMemoryOnCPU(); DestroyShadowMemoryOnPVC(); @@ -336,14 +200,30 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, auto ContextInfo = getContextInfo(Context); auto Addr = reinterpret_cast(Ptr); - auto AllocInfos = findAllocInfoByAddress(Addr, Context, nullptr); + auto AllocInfos = findAllocInfoByAddress(Addr); - if (!AllocInfos.size()) { + if (AllocInfos.empty()) { ReportBadFree(Addr, GetCurrentBacktrace(), nullptr); return UR_RESULT_ERROR_INVALID_ARGUMENT; } - for (auto AllocInfo : AllocInfos) { + std::vector> CurrentContext; + + for (auto It = AllocInfos.begin(); It != AllocInfos.end();) { + if (It->get()->Context == Context) { + CurrentContext.emplace_back(It); + It = AllocInfos.erase(It); + continue; + } + ++It; + } + + if (CurrentContext.empty()) { + // bad context + return UR_RESULT_ERROR_INVALID_ARGUMENT; + } + + for (auto &AllocInfo : CurrentContext) { context.logger.debug("AllocInfo(AllocBegin={}, UserBegin={})", (void *)AllocInfo->AllocBegin, (void *)AllocInfo->UserBegin); @@ -361,11 +241,17 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, AllocInfo->IsReleased = true; AllocInfo->ReleaseStack = GetCurrentBacktrace(); - auto Device = - getUSMAllocDevice(Context, (const void *)AllocInfo->AllocBegin); - + // auto Device = + // getUSMAllocDevice(Context, (const void *)AllocInfo->AllocBegin); + auto Device = AllocInfo->Device; // TODO: Check Device + // TODO: Quarantine Cache + if (m_Quarantine) { + auto ReleaseList = m_Quarantine->put(Device, AllocInfo); + for (auto &AI : ReleaseList) { + } + } // auto Res = // context.urDdiTable.USM.pfnFree(Context, (void *)AllocInfo->AllocBegin); @@ -734,6 +620,9 @@ ur_result_t SanitizerInterceptor::prepareLaunch( return true; }; + // Write debug + EnqueueWriteGlobal(kSPIR_AsanDebug, &cl_Debug, sizeof(cl_Debug)); + // Write shadow memory offset for global memory EnqueueWriteGlobal(kSPIR_AsanShadowMemoryGlobalStart, &DeviceInfo->ShadowOffset, @@ -802,9 +691,7 @@ ur_result_t SanitizerInterceptor::prepareLaunch( } std::vector> -SanitizerInterceptor::findAllocInfoByAddress(uptr Address, - ur_context_handle_t Context, - ur_device_handle_t Device) { +SanitizerInterceptor::findAllocInfoByAddress(uptr Address) { std::vector> Result; auto current = std::make_shared(USMAllocInfo{Address}); @@ -820,12 +707,6 @@ SanitizerInterceptor::findAllocInfoByAddress(uptr Address, if (AI->AllocBegin > Address) { break; } - if (Context && AI->Context != Context) { - continue; - } - if (Device && AI->Device != Device) { - continue; - } Result.emplace_back(*It); } return Result; diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 4e21d0fd41..1f4d6b8757 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -12,13 +12,13 @@ #pragma once +#include "asan_allocator.hpp" #include "common.hpp" #include "device_sanitizer_report.hpp" -#include "stacktrace.hpp" #include "ur_sanitizer_layer.hpp" -#include #include +#include #include #include #include @@ -26,31 +26,13 @@ namespace ur_sanitizer_layer { -enum MemoryType { DEVICE_USM, SHARED_USM, HOST_USM, MEM_BUFFER }; - -struct USMAllocInfo { - uptr AllocBegin = 0; - uptr UserBegin = 0; - uptr UserEnd = 0; - size_t AllocSize = 0; - - MemoryType Type = MemoryType::DEVICE_USM; - bool IsReleased = false; - - ur_context_handle_t Context = nullptr; - ur_device_handle_t Device = nullptr; - - StackTrace AllocStack; - StackTrace ReleaseStack; -}; +class Quarantine; struct USMAllocInfoList { std::vector> List; ur_shared_mutex Mutex; }; -enum class DeviceType : uint32_t { UNKNOWN = 0, CPU, GPU_PVC, GPU_DG2 }; - struct DeviceInfo { ur_device_handle_t Handle; @@ -59,6 +41,10 @@ struct DeviceInfo { uptr ShadowOffset = 0; uptr ShadowOffsetEnd = 0; + ur_mutex Mutex; + std::queue> Quarantine; + size_t QuarantineSize = 0; + DeviceInfo(ur_device_handle_t Device) : Handle(Device) { [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnRetain(Device); @@ -143,28 +129,9 @@ struct LaunchInfo { ~LaunchInfo(); }; -struct ManagedQueue { - ManagedQueue(ur_context_handle_t Context, ur_device_handle_t Device) { - [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnCreate( - Context, Device, nullptr, &Handle); - assert(Result == UR_RESULT_SUCCESS); - } - - ~ManagedQueue() { - [[maybe_unused]] auto Result = - context.urDdiTable.Queue.pfnRelease(Handle); - assert(Result == UR_RESULT_SUCCESS); - } - - operator ur_queue_handle_t() { return Handle; } - - private: - ur_queue_handle_t Handle = nullptr; -}; - class SanitizerInterceptor { public: - SanitizerInterceptor(); + explicit SanitizerInterceptor(); ~SanitizerInterceptor(); @@ -195,8 +162,7 @@ class SanitizerInterceptor { ur_queue_handle_t Queue); std::vector> - findAllocInfoByAddress(uptr Address, ur_context_handle_t Context, - ur_device_handle_t Device); + findAllocInfoByAddress(uptr Address); private: ur_result_t updateShadowMemory(std::shared_ptr &ContextInfo, @@ -259,8 +225,10 @@ class SanitizerInterceptor { AllocaionRangSet m_AllocationsMap; ur_shared_mutex m_AllocationsMapMutex; - bool m_IsInASanContext; - bool m_ShadowMemInited; + uint32_t cl_Debug = 0; + uint32_t cl_MaxQuarantineSizeMB = 0; + + std::unique_ptr m_Quarantine; }; } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_quarantine.cpp b/source/loader/layers/sanitizer/asan_quarantine.cpp new file mode 100644 index 0000000000..fec0e40c8f --- /dev/null +++ b/source/loader/layers/sanitizer/asan_quarantine.cpp @@ -0,0 +1,29 @@ +/* + * + * Copyright (C) 2024 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file asan_quarantine.cpp + * + */ + +#include "asan_quarantine.hpp" + +namespace ur_sanitizer_layer { + +std::vector> +Quarantine::put(ur_device_handle_t Device, std::shared_ptr &Ptr) { + auto AllocSize = Ptr->AllocSize; + auto &Cache = m_Map[Device]; + std::vector> DequeueList; + while (Cache.Size() + AllocSize > m_MaxQuarantineSize) { + DequeueList.emplace_back(Cache.Dequeue()); + } + m_Map[Device].Enqueue(Ptr); + return DequeueList; +} + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_quarantine.hpp b/source/loader/layers/sanitizer/asan_quarantine.hpp new file mode 100644 index 0000000000..a1f862959a --- /dev/null +++ b/source/loader/layers/sanitizer/asan_quarantine.hpp @@ -0,0 +1,74 @@ +/* + * + * Copyright (C) 2024 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file asan_quarantine.hpp + * + */ + +#pragma once + +#include "asan_allocator.hpp" + +#include +#include +#include +#include +#include + +namespace ur_sanitizer_layer { + +class QuarantineCache; + +class Quarantine { + public: + explicit Quarantine(size_t MaxQuarantineSize) + : m_MaxQuarantineSize(MaxQuarantineSize) {} + + std::vector> + put(ur_device_handle_t Device, std::shared_ptr &Ptr); + + private: + std::unordered_map m_Map; + size_t m_MaxQuarantineSize; +}; + +class QuarantineCache { + public: + explicit QuarantineCache(); + + // Total memory used, including internal accounting. + uptr Size() const { return m_Size; } + + // Memory used for internal accounting. + // uptr OverheadSize() const { return m_List.size() * sizeof(QuarantineBatch); } + + void Enqueue(std::shared_ptr &ptr) { + m_List.push(ptr); + m_Size += ptr->AllocSize; + } + + std::shared_ptr Dequeue() { + if (m_List.empty()) { + return nullptr; + } + auto b = m_List.front(); + m_List.pop(); + m_Size -= b->AllocSize; + return b; + } + + void PrintStats() const {} + + private: + typedef std::queue> List; + + List m_List; + std::atomic_uintptr_t m_Size; +}; + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp new file mode 100644 index 0000000000..a3a882ceba --- /dev/null +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -0,0 +1,102 @@ +/* + * + * Copyright (C) 2024 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file asan_report.cpp + * + */ + +#pragma once + +#include "asan_report.hpp" +#include "asan_allocator.hpp" +#include "device_sanitizer_report.hpp" +#include "ur_sanitizer_layer.hpp" +#include "ur_sanitizer_utils.hpp" + +namespace ur_sanitizer_layer { + +void ReportBadFree(uptr Addr, const StackTrace &stack, + std::shared_ptr AllocInfo) { + context.logger.always( + "\n====ERROR: DeviceSanitizer: attempting free on address which " + "was not malloc()-ed: {} in thread T0", + (void *)Addr); + stack.Print(); + + if (!AllocInfo) { // maybe Addr is host allocated memory + context.logger.always("{} is maybe allocated on Host Memory", + (void *)Addr); + exit(1); + } + + assert(!AllocInfo->IsReleased && "Chunk must be not released"); + + context.logger.always("{} is located inside of {} region [{}, {}]", + (void *)Addr, getFormatString(AllocInfo->Type), + (void *)AllocInfo->UserBegin, + (void *)AllocInfo->UserEnd); + context.logger.always("allocated by thread T0 here:"); + AllocInfo->AllocStack.Print(); + + exit(1); +} + +void ReportDoubleFree(uptr Addr, const StackTrace &Stack, + std::shared_ptr AllocInfo) { + context.logger.always("\n====ERROR: DeviceSanitizer: double-free on {}", + (void *)Addr); + Stack.Print(); + AllocInfo->AllocStack.Print(); + AllocInfo->ReleaseStack.Print(); + exit(1); +} + +void ReportGenericError(DeviceSanitizerReport &Report, + ur_kernel_handle_t Kernel, ur_context_handle_t Context, + ur_device_handle_t Device) { + const char *File = Report.File[0] ? Report.File : ""; + const char *Func = Report.Func[0] ? Report.Func : ""; + auto KernelName = getKernelName(Kernel); + + context.logger.always("\n====ERROR: DeviceSanitizer: {} on {}", + DeviceSanitizerFormat(Report.ErrorType), + DeviceSanitizerFormat(Report.MemoryType)); + context.logger.always( + "{} of size {} at kernel <{}> LID({}, {}, {}) GID({}, " + "{}, {})", + Report.IsWrite ? "WRITE" : "READ", Report.AccessSize, + KernelName.c_str(), Report.LID0, Report.LID1, Report.LID2, Report.GID0, + Report.GID1, Report.GID2); + context.logger.always(" #0 {} {}:{}\n", Func, File, Report.Line); + + if (Report.ErrorType == DeviceSanitizerErrorType::USE_AFTER_FREE) { + auto AllocInfos = + context.interceptor->findAllocInfoByAddress(Report.Addr); + if (!AllocInfos.size()) { + context.logger.always("can't find which chunck {} is allocated", + (void *)Report.Addr); + } + for (auto &AllocInfo : AllocInfos) { + if (!AllocInfo->IsReleased) { + continue; + } + context.logger.always( + "{} is located inside of {} region [{}, {}]", + (void *)Report.Addr, getFormatString(AllocInfo->Type), + (void *)AllocInfo->UserBegin, (void *)AllocInfo->UserEnd); + context.logger.always("allocated by thread T0 here:"); + AllocInfo->AllocStack.Print(); + context.logger.always("released by thread T0 here:"); + AllocInfo->ReleaseStack.Print(); + } + } + + exit(1); +} + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_report.hpp b/source/loader/layers/sanitizer/asan_report.hpp new file mode 100644 index 0000000000..f096f73a57 --- /dev/null +++ b/source/loader/layers/sanitizer/asan_report.hpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (C) 2024 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file asan_report.hpp + * + */ + +#pragma once + +#include "common.hpp" +#include + +namespace ur_sanitizer_layer { + +class DeviceSanitizerReport; +class USMAllocInfo; +class StackTrace; + +void ReportBadFree(uptr Addr, const StackTrace &stack, + std::shared_ptr AllocInfo); + +void ReportDoubleFree(uptr Addr, const StackTrace &Stack, + std::shared_ptr AllocInfo); + +void ReportGenericError(const DeviceSanitizerReport &Report, + ur_kernel_handle_t Kernel, ur_context_handle_t Context, + ur_device_handle_t Device); + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/common.hpp b/source/loader/layers/sanitizer/common.hpp index f095b75623..16e88169bd 100644 --- a/source/loader/layers/sanitizer/common.hpp +++ b/source/loader/layers/sanitizer/common.hpp @@ -91,6 +91,8 @@ struct AddressInfo { std::string debug; }; +enum class DeviceType : uint32_t { UNKNOWN = 0, CPU, GPU_PVC, GPU_DG2 }; + bool IsInASanContext(); bool MmapFixedNoReserve(uptr Addr, uptr Size); diff --git a/source/loader/layers/sanitizer/stacktrace.hpp b/source/loader/layers/sanitizer/stacktrace.hpp index e0225b4723..e6d69a46a3 100644 --- a/source/loader/layers/sanitizer/stacktrace.hpp +++ b/source/loader/layers/sanitizer/stacktrace.hpp @@ -23,7 +23,7 @@ namespace ur_sanitizer_layer { struct StackTrace { std::vector stack; - void Print(); + void Print() const; }; StackTrace GetCurrentBacktrace(); diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp new file mode 100644 index 0000000000..c6901c01cf --- /dev/null +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp @@ -0,0 +1,96 @@ +/* + * + * Copyright (C) 2023 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file ur_sanitizer_utils.cpp + * + */ + +#include "ur_sanitizer_utils.hpp" +#include "ur_sanitizer_layer.hpp" + +namespace ur_sanitizer_layer { + +ur_context_handle_t getContext(ur_queue_handle_t Queue) { + ur_context_handle_t Context{}; + [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( + Queue, UR_QUEUE_INFO_CONTEXT, sizeof(ur_context_handle_t), &Context, + nullptr); + assert(Result == UR_RESULT_SUCCESS && "getContext() failed"); + return Context; +} + +ur_device_handle_t getDevice(ur_queue_handle_t Queue) { + ur_device_handle_t Device{}; + [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( + Queue, UR_QUEUE_INFO_DEVICE, sizeof(ur_device_handle_t), &Device, + nullptr); + assert(Result == UR_RESULT_SUCCESS && "getDevice() failed"); + return Device; +} + +ur_program_handle_t getProgram(ur_kernel_handle_t Kernel) { + ur_program_handle_t Program{}; + [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( + Kernel, UR_KERNEL_INFO_PROGRAM, sizeof(ur_program_handle_t), &Program, + nullptr); + assert(Result == UR_RESULT_SUCCESS && "getProgram() failed"); + return Program; +} + +size_t getLocalMemorySize(ur_device_handle_t Device) { + size_t LocalMemorySize{}; + [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( + Device, UR_DEVICE_INFO_LOCAL_MEM_SIZE, sizeof(LocalMemorySize), + &LocalMemorySize, nullptr); + assert(Result == UR_RESULT_SUCCESS && "getLocalMemorySize() failed"); + return LocalMemorySize; +} + +std::string getKernelName(ur_kernel_handle_t Kernel) { + size_t KernelNameSize = 0; + [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( + Kernel, UR_KERNEL_INFO_FUNCTION_NAME, 0, nullptr, &KernelNameSize); + assert(Result == UR_RESULT_SUCCESS && "getKernelName() failed"); + + std::vector KernelNameBuf(KernelNameSize); + Result = context.urDdiTable.Kernel.pfnGetInfo( + Kernel, UR_KERNEL_INFO_FUNCTION_NAME, KernelNameSize, + KernelNameBuf.data(), nullptr); + assert(Result == UR_RESULT_SUCCESS && "getKernelName() failed"); + + return std::string(KernelNameBuf.data(), KernelNameSize - 1); +} + +ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, + const void *MemPtr) { + ur_device_handle_t Device{}; + // if urGetMemAllocInfo failed, return nullptr + context.urDdiTable.USM.pfnGetMemAllocInfo(Context, MemPtr, + UR_USM_ALLOC_INFO_DEVICE, + sizeof(Device), &Device, nullptr); + return Device; +} + +DeviceType getDeviceType(ur_device_handle_t Device) { + ur_device_type_t DeviceType = UR_DEVICE_TYPE_DEFAULT; + [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( + Device, UR_DEVICE_INFO_TYPE, sizeof(DeviceType), &DeviceType, nullptr); + assert(Result == UR_RESULT_SUCCESS && "getDeviceType() failed"); + switch (DeviceType) { + case UR_DEVICE_TYPE_CPU: + return DeviceType::CPU; + case UR_DEVICE_TYPE_GPU: { + // TODO: Check device name + return DeviceType::GPU_PVC; + } + default: + return DeviceType::UNKNOWN; + } +} + +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp new file mode 100644 index 0000000000..5518e02020 --- /dev/null +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp @@ -0,0 +1,28 @@ +/* + * + * Copyright (C) 2023 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See LICENSE.TXT + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * @file ur_sanitizer_utils.hpp + * + */ + +#pragma once + +#include "common.hpp" + +namespace ur_sanitizer_layer { + +ur_context_handle_t getContext(ur_queue_handle_t Queue); +ur_device_handle_t getDevice(ur_queue_handle_t Queue); +ur_program_handle_t getProgram(ur_kernel_handle_t Kernel); +size_t getLocalMemorySize(ur_device_handle_t Device); +std::string getKernelName(ur_kernel_handle_t Kernel); +ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, + const void *MemPtr); +DeviceType getDeviceType(ur_device_handle_t Device); + +} // namespace ur_sanitizer_layer From 5467e409c594e5ca82ebd0cd06b156b5dfe821f5 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 27 Feb 2024 03:27:45 -0800 Subject: [PATCH 14/42] fix build --- source/loader/CMakeLists.txt | 20 ++++++++--- .../layers/sanitizer/asan_allocator.cpp | 17 --------- .../layers/sanitizer/asan_interceptor.cpp | 2 +- .../layers/sanitizer/asan_quarantine.cpp | 6 ++-- .../layers/sanitizer/asan_quarantine.hpp | 36 +++++++++---------- .../loader/layers/sanitizer/asan_report.cpp | 17 +++++---- .../loader/layers/sanitizer/asan_report.hpp | 7 ++-- source/loader/layers/sanitizer/common.hpp | 9 +++-- .../layers/sanitizer/linux/backtrace.cpp | 5 ++- .../sanitizer/linux/sanitizer_utils.cpp | 13 +++++++ source/loader/layers/sanitizer/stacktrace.cpp | 25 +++++++------ source/loader/layers/sanitizer/stacktrace.hpp | 2 +- .../sanitizer/{linux => }/symbolizer_llvm.cpp | 34 +++++------------- .../layers/sanitizer/symbolizer_llvm.hpp | 8 ++--- 14 files changed, 98 insertions(+), 103 deletions(-) rename source/loader/layers/sanitizer/{linux => }/symbolizer_llvm.cpp (50%) diff --git a/source/loader/CMakeLists.txt b/source/loader/CMakeLists.txt index 6057bfebf1..1f3705eeaa 100644 --- a/source/loader/CMakeLists.txt +++ b/source/loader/CMakeLists.txt @@ -106,25 +106,35 @@ if(UR_ENABLE_SANITIZER) target_sources(ur_loader PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../ur/ur.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_allocator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_allocator.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_interceptor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_interceptor.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_quarantine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_quarantine.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_report.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_report.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/common.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/device_sanitizer_report.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/stacktrace.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/stacktrace.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/symbolizer_llvm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/symbolizer_llvm.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanddi.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/symbolizer_llvm.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_utils.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_utils.hpp ) target_sources(ur_loader PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/sanitizer_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/backtrace.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/symbolizer_llvm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/sanitizer_utils.cpp ) target_include_directories(ur_loader PRIVATE diff --git a/source/loader/layers/sanitizer/asan_allocator.cpp b/source/loader/layers/sanitizer/asan_allocator.cpp index c0895a698e..f6fe9f903d 100644 --- a/source/loader/layers/sanitizer/asan_allocator.cpp +++ b/source/loader/layers/sanitizer/asan_allocator.cpp @@ -10,25 +10,8 @@ * */ -#pragma once - #include "asan_allocator.hpp" namespace ur_sanitizer_layer { -const char *getFormatString(MemoryType MemoryType) { - switch (MemoryType) { - case MemoryType::DEVICE_USM: - return "USM Device Memory"; - case MemoryType::HOST_USM: - return "USM Host Memory"; - case MemoryType::SHARED_USM: - return "USM Shared Memory"; - case MemoryType::MEM_BUFFER: - return "Memory Buffer"; - default: - return "Unknown Memory"; - } -} - } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index a06689067b..f4201353fb 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -214,7 +214,7 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, for (auto It = AllocInfos.begin(); It != AllocInfos.end();) { if (It->get()->Context == Context) { - CurrentContext.emplace_back(It); + CurrentContext.emplace_back(*It); It = AllocInfos.erase(It); continue; } diff --git a/source/loader/layers/sanitizer/asan_quarantine.cpp b/source/loader/layers/sanitizer/asan_quarantine.cpp index fec0e40c8f..a12b875400 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.cpp +++ b/source/loader/layers/sanitizer/asan_quarantine.cpp @@ -14,11 +14,11 @@ namespace ur_sanitizer_layer { -std::vector> -Quarantine::put(ur_device_handle_t Device, std::shared_ptr &Ptr) { +std::vector> +Quarantine::put(ur_device_handle_t Device, std::shared_ptr &Ptr) { auto AllocSize = Ptr->AllocSize; auto &Cache = m_Map[Device]; - std::vector> DequeueList; + std::vector> DequeueList; while (Cache.Size() + AllocSize > m_MaxQuarantineSize) { DequeueList.emplace_back(Cache.Dequeue()); } diff --git a/source/loader/layers/sanitizer/asan_quarantine.hpp b/source/loader/layers/sanitizer/asan_quarantine.hpp index a1f862959a..bed4728c9f 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.hpp +++ b/source/loader/layers/sanitizer/asan_quarantine.hpp @@ -22,24 +22,9 @@ namespace ur_sanitizer_layer { -class QuarantineCache; - -class Quarantine { - public: - explicit Quarantine(size_t MaxQuarantineSize) - : m_MaxQuarantineSize(MaxQuarantineSize) {} - - std::vector> - put(ur_device_handle_t Device, std::shared_ptr &Ptr); - - private: - std::unordered_map m_Map; - size_t m_MaxQuarantineSize; -}; - class QuarantineCache { public: - explicit QuarantineCache(); + explicit QuarantineCache() {} // Total memory used, including internal accounting. uptr Size() const { return m_Size; } @@ -47,12 +32,12 @@ class QuarantineCache { // Memory used for internal accounting. // uptr OverheadSize() const { return m_List.size() * sizeof(QuarantineBatch); } - void Enqueue(std::shared_ptr &ptr) { + void Enqueue(std::shared_ptr &ptr) { m_List.push(ptr); m_Size += ptr->AllocSize; } - std::shared_ptr Dequeue() { + std::shared_ptr Dequeue() { if (m_List.empty()) { return nullptr; } @@ -65,10 +50,23 @@ class QuarantineCache { void PrintStats() const {} private: - typedef std::queue> List; + typedef std::queue> List; List m_List; std::atomic_uintptr_t m_Size; }; +class Quarantine { + public: + explicit Quarantine(size_t MaxQuarantineSize) + : m_MaxQuarantineSize(MaxQuarantineSize) {} + + std::vector> + put(ur_device_handle_t Device, std::shared_ptr &Ptr); + + private: + std::unordered_map m_Map; + size_t m_MaxQuarantineSize; +}; + } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index a3a882ceba..c4ff9faf82 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -10,10 +10,9 @@ * */ -#pragma once - #include "asan_report.hpp" #include "asan_allocator.hpp" +#include "asan_interceptor.hpp" #include "device_sanitizer_report.hpp" #include "ur_sanitizer_layer.hpp" #include "ur_sanitizer_utils.hpp" @@ -21,7 +20,7 @@ namespace ur_sanitizer_layer { void ReportBadFree(uptr Addr, const StackTrace &stack, - std::shared_ptr AllocInfo) { + std::shared_ptr AllocInfo) { context.logger.always( "\n====ERROR: DeviceSanitizer: attempting free on address which " "was not malloc()-ed: {} in thread T0", @@ -37,7 +36,7 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, assert(!AllocInfo->IsReleased && "Chunk must be not released"); context.logger.always("{} is located inside of {} region [{}, {}]", - (void *)Addr, getFormatString(AllocInfo->Type), + (void *)Addr, ToString(AllocInfo->Type), (void *)AllocInfo->UserBegin, (void *)AllocInfo->UserEnd); context.logger.always("allocated by thread T0 here:"); @@ -47,7 +46,7 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, } void ReportDoubleFree(uptr Addr, const StackTrace &Stack, - std::shared_ptr AllocInfo) { + std::shared_ptr AllocInfo) { context.logger.always("\n====ERROR: DeviceSanitizer: double-free on {}", (void *)Addr); Stack.Print(); @@ -56,7 +55,7 @@ void ReportDoubleFree(uptr Addr, const StackTrace &Stack, exit(1); } -void ReportGenericError(DeviceSanitizerReport &Report, +void ReportGenericError(const DeviceSanitizerReport &Report, ur_kernel_handle_t Kernel, ur_context_handle_t Context, ur_device_handle_t Device) { const char *File = Report.File[0] ? Report.File : ""; @@ -64,8 +63,8 @@ void ReportGenericError(DeviceSanitizerReport &Report, auto KernelName = getKernelName(Kernel); context.logger.always("\n====ERROR: DeviceSanitizer: {} on {}", - DeviceSanitizerFormat(Report.ErrorType), - DeviceSanitizerFormat(Report.MemoryType)); + ToString(Report.ErrorType), + ToString(Report.MemoryType)); context.logger.always( "{} of size {} at kernel <{}> LID({}, {}, {}) GID({}, " "{}, {})", @@ -87,7 +86,7 @@ void ReportGenericError(DeviceSanitizerReport &Report, } context.logger.always( "{} is located inside of {} region [{}, {}]", - (void *)Report.Addr, getFormatString(AllocInfo->Type), + (void *)Report.Addr, ToString(AllocInfo->Type), (void *)AllocInfo->UserBegin, (void *)AllocInfo->UserEnd); context.logger.always("allocated by thread T0 here:"); AllocInfo->AllocStack.Print(); diff --git a/source/loader/layers/sanitizer/asan_report.hpp b/source/loader/layers/sanitizer/asan_report.hpp index f096f73a57..e8fc8c0463 100644 --- a/source/loader/layers/sanitizer/asan_report.hpp +++ b/source/loader/layers/sanitizer/asan_report.hpp @@ -13,19 +13,20 @@ #pragma once #include "common.hpp" + #include namespace ur_sanitizer_layer { class DeviceSanitizerReport; -class USMAllocInfo; +class AllocInfo; class StackTrace; void ReportBadFree(uptr Addr, const StackTrace &stack, - std::shared_ptr AllocInfo); + std::shared_ptr AllocInfo); void ReportDoubleFree(uptr Addr, const StackTrace &Stack, - std::shared_ptr AllocInfo); + std::shared_ptr AllocInfo); void ReportGenericError(const DeviceSanitizerReport &Report, ur_kernel_handle_t Kernel, ur_context_handle_t Context, diff --git a/source/loader/layers/sanitizer/common.hpp b/source/loader/layers/sanitizer/common.hpp index f0567a8e6b..4da9cea3d9 100644 --- a/source/loader/layers/sanitizer/common.hpp +++ b/source/loader/layers/sanitizer/common.hpp @@ -82,14 +82,17 @@ inline constexpr uptr ComputeRZLog(uptr user_requested_size) { return Result; \ } -struct AddressInfo { +struct BacktraceInfo { uptr offset; std::string module; + std::string debug; +}; + +struct SourceInfo { std::string file; std::string function; int line; int column; - std::string debug; }; enum class DeviceType : uint32_t { UNKNOWN = 0, CPU, GPU_PVC, GPU_DG2 }; @@ -104,4 +107,6 @@ void *GetMemFunctionPointer(const char *); std::string DemangleName(const std::string &name); +std::string RunCommand(const char *cmd); + } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/linux/backtrace.cpp b/source/loader/layers/sanitizer/linux/backtrace.cpp index 732d35adb4..b31fab3300 100644 --- a/source/loader/layers/sanitizer/linux/backtrace.cpp +++ b/source/loader/layers/sanitizer/linux/backtrace.cpp @@ -8,7 +8,6 @@ * */ #include "stacktrace.hpp" -#include "ur_sanitizer_layer.hpp" #include #include @@ -16,7 +15,7 @@ namespace ur_sanitizer_layer { -bool ExtractSymbolInfo(const char *symbol, AddressInfo &info) { +bool ExtractSymbolInfo(const char *symbol, BacktraceInfo &info) { info.debug = std::string(symbol); auto s1 = std::strrchr(symbol, '('); @@ -37,7 +36,7 @@ StackTrace GetCurrentBacktrace() { StackTrace stack; for (int i = 0; i < frameCount; i++) { - AddressInfo addr_info; + BacktraceInfo addr_info; if (!ExtractSymbolInfo(backtraceStr[i], addr_info)) { continue; } diff --git a/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp b/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp index 63718207ba..430bcc4c8a 100644 --- a/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp +++ b/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp @@ -69,4 +69,17 @@ std::string DemangleName(const std::string &name) { return result; } +std::string RunCommand(const char *cmd) { + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(cmd, "r"), pclose); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + return result; +} + } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/stacktrace.cpp b/source/loader/layers/sanitizer/stacktrace.cpp index 737c6d83ca..b4e4b9635b 100644 --- a/source/loader/layers/sanitizer/stacktrace.cpp +++ b/source/loader/layers/sanitizer/stacktrace.cpp @@ -29,29 +29,32 @@ bool startWith(const std::string &Str, const char *Pattern) { return Str.rfind(Pattern, 0) == 0; } -void StackTrace::Print() { +void StackTrace::Print() const { if (!stack.size()) { context.logger.always(" failed to acquire backtrace"); } - LLVMSymbolizer symbolizer(""); + + LLVMSymbolizer symbolizer; unsigned index = 0; - for (auto &Addr : stack) { - auto ModuleFile = getFileName(Addr.module); + + for (auto &BI : stack) { + auto ModuleFile = getFileName(BI.module); if (startWith(ModuleFile, "libsycl.so") || startWith(ModuleFile, "libpi_unified_runtime.so") || startWith(ModuleFile, "libur_loader.so")) { continue; } - symbolizer.SymbolizePC(&Addr); - if (!Addr.file.empty()) { + SourceInfo SI; + symbolizer.SymbolizePC(BI, SI); + + if (!SI.file.empty()) { context.logger.always(" #{} {} in {} {}:{}:{}", index, - (void *)Addr.offset, Addr.function, Addr.file, - Addr.line, Addr.column); + (void *)BI.offset, SI.function, SI.file, + SI.line, SI.column); } else { - context.logger.always(" #{} {} in {} {}", index, - (void *)Addr.offset, Addr.function, - Addr.module); + context.logger.always(" #{} {} in {} {}", index, (void *)BI.offset, + SI.function, BI.module); } ++index; } diff --git a/source/loader/layers/sanitizer/stacktrace.hpp b/source/loader/layers/sanitizer/stacktrace.hpp index e6d69a46a3..2c6eb6f756 100644 --- a/source/loader/layers/sanitizer/stacktrace.hpp +++ b/source/loader/layers/sanitizer/stacktrace.hpp @@ -21,7 +21,7 @@ namespace ur_sanitizer_layer { #define MAX_BACKTRACE_FRAMES 64 struct StackTrace { - std::vector stack; + std::vector stack; void Print() const; }; diff --git a/source/loader/layers/sanitizer/linux/symbolizer_llvm.cpp b/source/loader/layers/sanitizer/symbolizer_llvm.cpp similarity index 50% rename from source/loader/layers/sanitizer/linux/symbolizer_llvm.cpp rename to source/loader/layers/sanitizer/symbolizer_llvm.cpp index 8e57a981cf..5c4a34f6c8 100644 --- a/source/loader/layers/sanitizer/linux/symbolizer_llvm.cpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.cpp @@ -11,27 +11,13 @@ */ #include "symbolizer_llvm.hpp" -#include "ur_sanitizer_layer.hpp" #include #include namespace ur_sanitizer_layer { -std::string exec(const char *cmd) { - std::array buffer; - std::string result; - std::unique_ptr pipe(popen(cmd, "r"), pclose); - if (!pipe) { - throw std::runtime_error("popen() failed!"); - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; -} - -bool ExtractInfo(const std::string &output, AddressInfo *Info) { +bool ExtractSourceInfo(const std::string &output, SourceInfo &SI) { auto p1 = output.find('\n'); std::string function = output.substr(0, p1); auto p2 = output.find(':', ++p1); @@ -40,24 +26,22 @@ bool ExtractInfo(const std::string &output, AddressInfo *Info) { int line = std::stoi(output.substr(p2, p3 - p2)); int column = std::stoi(output.substr(++p3)); if (function != "??") { - Info->function = std::move(function); + SI.function = std::move(function); } if (file != "??") { - Info->file = std::move(file); + SI.file = std::move(file); } - Info->line = line; - Info->column = column; + SI.line = line; + SI.column = column; return true; } -LLVMSymbolizer::LLVMSymbolizer(const char *path) {} - -bool LLVMSymbolizer::SymbolizePC(AddressInfo *Info) { +bool LLVMSymbolizer::SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { std::stringstream ss; - ss << "llvm-symbolizer --obj=" << Info->module << " " << Info->offset; - auto result = exec(ss.str().c_str()); + ss << "llvm-symbolizer --obj=" << BI.module << " " << BI.offset; + auto result = RunCommand(ss.str().c_str()); // context.logger.debug("llvm-symbolizer: {}", result); - ExtractInfo(result, Info); + ExtractSourceInfo(result, SI); return true; } diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.hpp b/source/loader/layers/sanitizer/symbolizer_llvm.hpp index 7588f27119..23ec756e3d 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.hpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.hpp @@ -17,14 +17,14 @@ namespace ur_sanitizer_layer { class SymbolizerTool { - virtual bool SymbolizePC(AddressInfo *Info) { return false; } + virtual bool SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { + return false; + } }; class LLVMSymbolizer final : public SymbolizerTool { public: - explicit LLVMSymbolizer(const char *path); - - bool SymbolizePC(AddressInfo *Info) override; + bool SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) override; }; } // namespace ur_sanitizer_layer From e8f8674492b85f332ffd4a108385f2df88bba13c Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 28 Feb 2024 21:40:46 -0800 Subject: [PATCH 15/42] fix out-of-bounds test --- source/loader/layers/sanitizer/asan_interceptor.cpp | 3 +++ source/loader/layers/sanitizer/asan_report.cpp | 3 +++ source/loader/layers/sanitizer/common.hpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index f4201353fb..c282eff6ec 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -87,6 +87,9 @@ uptr MemToShadow_PVC(uptr USM_SHADOW_BASE, uptr UPtr) { SanitizerInterceptor::SanitizerInterceptor() { auto Options = getenv_to_map("UR_LAYER_ASAN_OPTIONS"); + if (!Options.has_value()) { + return; + } auto KV = Options->find("debug"); if (KV != Options->end()) { auto Value = KV->second.front(); diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index c4ff9faf82..aef706a049 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -62,6 +62,9 @@ void ReportGenericError(const DeviceSanitizerReport &Report, const char *Func = Report.Func[0] ? Report.Func : ""; auto KernelName = getKernelName(Kernel); + // Try to demangle the kernel name + KernelName = DemangleName(KernelName); + context.logger.always("\n====ERROR: DeviceSanitizer: {} on {}", ToString(Report.ErrorType), ToString(Report.MemoryType)); diff --git a/source/loader/layers/sanitizer/common.hpp b/source/loader/layers/sanitizer/common.hpp index 4da9cea3d9..dab6b61957 100644 --- a/source/loader/layers/sanitizer/common.hpp +++ b/source/loader/layers/sanitizer/common.hpp @@ -95,7 +95,7 @@ struct SourceInfo { int column; }; -enum class DeviceType : uint32_t { UNKNOWN = 0, CPU, GPU_PVC, GPU_DG2 }; +enum class DeviceType : uint64_t { UNKNOWN = 0, CPU, GPU_PVC, GPU_DG2 }; bool IsInASanContext(); From f697026742a77e03fe06041fe4a692cbc335f3df Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Fri, 1 Mar 2024 01:37:40 -0800 Subject: [PATCH 16/42] update report --- .../layers/sanitizer/asan_interceptor.cpp | 1 + .../loader/layers/sanitizer/asan_report.cpp | 58 +++++++++++++------ .../loader/layers/sanitizer/asan_report.hpp | 4 ++ 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index c282eff6ec..266304bca7 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -226,6 +226,7 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, if (CurrentContext.empty()) { // bad context + ReportBadFreeContext(Addr, GetCurrentBacktrace(), AllocInfos); return UR_RESULT_ERROR_INVALID_ARGUMENT; } diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index aef706a049..9151e86467 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -20,38 +20,62 @@ namespace ur_sanitizer_layer { void ReportBadFree(uptr Addr, const StackTrace &stack, - std::shared_ptr AllocInfo) { - context.logger.always( - "\n====ERROR: DeviceSanitizer: attempting free on address which " - "was not malloc()-ed: {} in thread T0", - (void *)Addr); + std::shared_ptr AI) { + context.logger.always("\n====ERROR: DeviceSanitizer: bad-free on {}", + (void *)Addr); stack.Print(); - if (!AllocInfo) { // maybe Addr is host allocated memory - context.logger.always("{} is maybe allocated on Host Memory", + if (!AI) { // maybe Addr is host allocated memory + context.logger.always("{} may be allocated on Host Memory", (void *)Addr); exit(1); } - assert(!AllocInfo->IsReleased && "Chunk must be not released"); + assert(!AI->IsReleased && "Chunk must be not released"); - context.logger.always("{} is located inside of {} region [{}, {}]", - (void *)Addr, ToString(AllocInfo->Type), - (void *)AllocInfo->UserBegin, - (void *)AllocInfo->UserEnd); - context.logger.always("allocated by thread T0 here:"); - AllocInfo->AllocStack.Print(); + context.logger.always("{} is located inside of {} region [{}, {})", + (void *)Addr, ToString(AI->Type), + (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); + context.logger.always("allocated here:"); + AI->AllocStack.Print(); exit(1); } +void ReportBadFreeContext( + uptr Addr, const StackTrace &stack, + const std::vector> &AllocInfos) { + context.logger.always( + "\n====ERROR: DeviceSanitizer: bad-free-context on {}", (void *)Addr); + stack.Print(); + + for (auto &AI : AllocInfos) { + if (AI->IsReleased) { + continue; + } + context.logger.always("{} is located inside of {} region [{}, {})", + (void *)Addr, ToString(AI->Type), + (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); + context.logger.always( + "allocated here:"); // allocated by device, context + AI->AllocStack.Print(); + } + exit(1); +} + void ReportDoubleFree(uptr Addr, const StackTrace &Stack, - std::shared_ptr AllocInfo) { + std::shared_ptr AI) { context.logger.always("\n====ERROR: DeviceSanitizer: double-free on {}", (void *)Addr); Stack.Print(); - AllocInfo->AllocStack.Print(); - AllocInfo->ReleaseStack.Print(); + + context.logger.always("{} is located inside of {} region [{}, {})", + (void *)Addr, ToString(AI->Type), + (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); + context.logger.always("freed here:"); + AI->ReleaseStack.Print(); + context.logger.always("previously allocated here:"); + AI->AllocStack.Print(); exit(1); } diff --git a/source/loader/layers/sanitizer/asan_report.hpp b/source/loader/layers/sanitizer/asan_report.hpp index e8fc8c0463..ec1cdccc48 100644 --- a/source/loader/layers/sanitizer/asan_report.hpp +++ b/source/loader/layers/sanitizer/asan_report.hpp @@ -25,6 +25,10 @@ class StackTrace; void ReportBadFree(uptr Addr, const StackTrace &stack, std::shared_ptr AllocInfo); +void ReportBadFreeContext( + uptr Addr, const StackTrace &stack, + const std::vector> &AllocInfos); + void ReportDoubleFree(uptr Addr, const StackTrace &Stack, std::shared_ptr AllocInfo); From 73fbdfe6f41f07f9f7f91ad7a65d5703ba148d8f Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sat, 2 Mar 2024 23:56:14 -0800 Subject: [PATCH 17/42] Use iterator to pass AllocInfo --- .../layers/sanitizer/asan_allocator.hpp | 6 + .../layers/sanitizer/asan_interceptor.cpp | 117 +++++++----------- .../layers/sanitizer/asan_interceptor.hpp | 22 +--- .../layers/sanitizer/asan_quarantine.cpp | 17 ++- .../loader/layers/sanitizer/asan_report.cpp | 63 +++++----- 5 files changed, 98 insertions(+), 127 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_allocator.hpp b/source/loader/layers/sanitizer/asan_allocator.hpp index e29e79d410..c7cf89c2ba 100644 --- a/source/loader/layers/sanitizer/asan_allocator.hpp +++ b/source/loader/layers/sanitizer/asan_allocator.hpp @@ -15,6 +15,9 @@ #include "common.hpp" #include "stacktrace.hpp" +#include +#include + namespace ur_sanitizer_layer { enum class AllocType : uint32_t { @@ -41,6 +44,9 @@ struct AllocInfo { StackTrace ReleaseStack; }; +using AllocationMap = std::map>; +using AllocationIterator = AllocationMap::iterator; + inline const char *ToString(AllocType Type) { switch (Type) { case AllocType::DEVICE_USM: diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 266304bca7..f10771168b 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -189,8 +189,8 @@ ur_result_t SanitizerInterceptor::allocateMemory( // For memory release { - std::scoped_lock Guard(m_AllocationsMapMutex); - m_AllocationsMap.emplace(std::move(AI)); + std::scoped_lock Guard(m_AllocationMapMutex); + m_AllocationMap.emplace(AI->AllocBegin, std::move(AI)); } context.logger.info( @@ -206,71 +206,58 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, auto ContextInfo = getContextInfo(Context); auto Addr = reinterpret_cast(Ptr); - auto AllocInfos = findAllocInfoByAddress(Addr); + auto AllocInfoItOp = findAllocInfoByAddress(Addr); - if (AllocInfos.empty()) { + if (!AllocInfoItOp) { ReportBadFree(Addr, GetCurrentBacktrace(), nullptr); return UR_RESULT_ERROR_INVALID_ARGUMENT; } - std::vector> CurrentContext; + auto AllocInfoIt = *AllocInfoItOp; + auto &AllocInfo = AllocInfoIt->second; - for (auto It = AllocInfos.begin(); It != AllocInfos.end();) { - if (It->get()->Context == Context) { - CurrentContext.emplace_back(*It); - It = AllocInfos.erase(It); - continue; + context.logger.debug("AllocInfo(AllocBegin={}, UserBegin={})", + (void *)AllocInfo->AllocBegin, + (void *)AllocInfo->UserBegin); + + if (AllocInfo->Context != Context) { + if (AllocInfo->UserBegin == Addr) { + ReportBadFreeContext(Addr, GetCurrentBacktrace(), AllocInfo); + } else { + ReportBadFree(Addr, GetCurrentBacktrace(), nullptr); } - ++It; + return UR_RESULT_ERROR_INVALID_ARGUMENT; } - if (CurrentContext.empty()) { - // bad context - ReportBadFreeContext(Addr, GetCurrentBacktrace(), AllocInfos); + if (Addr != AllocInfo->UserBegin) { + ReportBadFree(Addr, GetCurrentBacktrace(), AllocInfo); return UR_RESULT_ERROR_INVALID_ARGUMENT; } - for (auto &AllocInfo : CurrentContext) { - context.logger.debug("AllocInfo(AllocBegin={}, UserBegin={})", - (void *)AllocInfo->AllocBegin, - (void *)AllocInfo->UserBegin); - - if (AllocInfo->IsReleased) { - ReportDoubleFree(Addr, GetCurrentBacktrace(), AllocInfo); - return UR_RESULT_ERROR_INVALID_ARGUMENT; - } - - if (Addr != AllocInfo->UserBegin) { - ReportBadFree(Addr, GetCurrentBacktrace(), AllocInfo); - return UR_RESULT_ERROR_INVALID_ARGUMENT; - } + if (AllocInfo->IsReleased) { + ReportDoubleFree(Addr, GetCurrentBacktrace(), AllocInfo); + return UR_RESULT_ERROR_INVALID_ARGUMENT; + } - AllocInfo->IsReleased = true; - AllocInfo->ReleaseStack = GetCurrentBacktrace(); + AllocInfo->IsReleased = true; + AllocInfo->ReleaseStack = GetCurrentBacktrace(); - // auto Device = - // getUSMAllocDevice(Context, (const void *)AllocInfo->AllocBegin); - auto Device = AllocInfo->Device; - // TODO: Check Device + auto Device = AllocInfo->Device; - // TODO: Quarantine Cache - if (m_Quarantine) { - auto ReleaseList = m_Quarantine->put(Device, AllocInfo); - for (auto &AI : ReleaseList) { - } + if (m_Quarantine) { + auto ReleaseList = m_Quarantine->put(Device, AllocInfoIt); + std::scoped_lock Guard(m_AllocationMapMutex); + for (auto &It : ReleaseList) { + context.urDdiTable.USM.pfnFree(Context, + (void *)(It->second->AllocBegin)); + m_AllocationMap.erase(It); } + } - // auto Res = - // context.urDdiTable.USM.pfnFree(Context, (void *)AllocInfo->AllocBegin); - // if (Res != UR_RESULT_SUCCESS) { - // return Res; - // } - - if (AllocInfo->Type == AllocType::HOST_USM) { - ContextInfo->insertAllocInfo(ContextInfo->DeviceList, AllocInfo); - } else { - ContextInfo->insertAllocInfo({Device}, AllocInfo); - } + if (AllocInfo->Type == AllocType::HOST_USM) { + ContextInfo->insertAllocInfo(ContextInfo->DeviceList, AllocInfo); + } else { + ContextInfo->insertAllocInfo({Device}, AllocInfo); } return UR_RESULT_SUCCESS; @@ -318,11 +305,11 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, if (Result == UR_RESULT_SUCCESS) { Event = ReadEvent; - auto AH = &LaunchInfo.SPIR_DeviceSanitizerReportMem; - if (!AH->Flag) { + const auto &AH = LaunchInfo.SPIR_DeviceSanitizerReportMem; + if (AH.Flag) { return; } - ReportGenericError(*AH, Kernel, getContext(Queue), getDevice(Queue)); + ReportGenericError(AH, Kernel, getContext(Queue)); } } @@ -750,26 +737,12 @@ ur_result_t SanitizerInterceptor::prepareLaunch( return UR_RESULT_SUCCESS; } -std::vector> +std::optional SanitizerInterceptor::findAllocInfoByAddress(uptr Address) { - std::vector> Result; - auto current = std::make_shared(AllocInfo{Address}); - - std::shared_lock Guard(m_AllocationsMapMutex); - - auto It = std::lower_bound( - m_AllocationsMap.begin(), m_AllocationsMap.end(), Address, - [](const std::shared_ptr &AllocInfo, uptr Addr) { - return (AllocInfo->AllocBegin + AllocInfo->AllocSize) < Addr; - }); - for (; It != m_AllocationsMap.end(); ++It) { - auto AI = *It; - if (AI->AllocBegin > Address) { - break; - } - Result.emplace_back(*It); - } - return Result; + std::shared_lock Guard(m_AllocationMapMutex); + auto It = m_AllocationMap.lower_bound(Address); + return It == m_AllocationMap.end() ? std::optional{} + : It; } LaunchInfo::~LaunchInfo() { diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 20e0a014fd..057457e37d 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -18,6 +18,7 @@ #include "ur_sanitizer_layer.hpp" #include +#include #include #include #include @@ -170,8 +171,7 @@ class SanitizerInterceptor { ur_result_t eraseQueue(ur_context_handle_t Context, ur_queue_handle_t Queue); - std::vector> - findAllocInfoByAddress(uptr Address); + std::optional findAllocInfoByAddress(uptr Address); private: ur_result_t updateShadowMemory(std::shared_ptr &ContextInfo, @@ -217,22 +217,8 @@ class SanitizerInterceptor { m_DeviceMap; ur_shared_mutex m_DeviceMapMutex; - struct AllocInfoCompare { - bool operator()(const std::shared_ptr &lhs, - const std::shared_ptr &rhs) const { - auto p1 = std::make_pair(lhs->AllocBegin, - lhs->AllocBegin + lhs->AllocSize); - auto p2 = std::make_pair(rhs->AllocBegin, - rhs->AllocBegin + rhs->AllocSize); - return p1 < p2; - } - }; - - using AllocaionRangSet = - std::multiset, AllocInfoCompare>; - - AllocaionRangSet m_AllocationsMap; - ur_shared_mutex m_AllocationsMapMutex; + AllocationMap m_AllocationMap; + ur_shared_mutex m_AllocationMapMutex; uint32_t cl_Debug = 0; uint32_t cl_MaxQuarantineSizeMB = 0; diff --git a/source/loader/layers/sanitizer/asan_quarantine.cpp b/source/loader/layers/sanitizer/asan_quarantine.cpp index a12b875400..99e3d6173b 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.cpp +++ b/source/loader/layers/sanitizer/asan_quarantine.cpp @@ -14,15 +14,20 @@ namespace ur_sanitizer_layer { -std::vector> -Quarantine::put(ur_device_handle_t Device, std::shared_ptr &Ptr) { - auto AllocSize = Ptr->AllocSize; +std::vector Quarantine::put(ur_device_handle_t Device, + AllocationIterator &It) { + auto &AI = It->second; + auto AllocSize = AI->AllocSize; auto &Cache = m_Map[Device]; - std::vector> DequeueList; + std::vector DequeueList; while (Cache.Size() + AllocSize > m_MaxQuarantineSize) { - DequeueList.emplace_back(Cache.Dequeue()); + auto ItOp = Cache.Dequeue(); + if (!ItOp) { + break; + } + DequeueList.emplace_back(*ItOp); } - m_Map[Device].Enqueue(Ptr); + m_Map[Device].Enqueue(It); return DequeueList; } diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index 9151e86467..496f60854d 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -20,7 +20,7 @@ namespace ur_sanitizer_layer { void ReportBadFree(uptr Addr, const StackTrace &stack, - std::shared_ptr AI) { + const std::shared_ptr &AI) { context.logger.always("\n====ERROR: DeviceSanitizer: bad-free on {}", (void *)Addr); stack.Print(); @@ -42,29 +42,28 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, exit(1); } -void ReportBadFreeContext( - uptr Addr, const StackTrace &stack, - const std::vector> &AllocInfos) { +void ReportBadFreeContext(uptr Addr, const StackTrace &stack, + const std::shared_ptr &AI) { context.logger.always( "\n====ERROR: DeviceSanitizer: bad-free-context on {}", (void *)Addr); stack.Print(); - for (auto &AI : AllocInfos) { - if (AI->IsReleased) { - continue; - } - context.logger.always("{} is located inside of {} region [{}, {})", - (void *)Addr, ToString(AI->Type), - (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); - context.logger.always( - "allocated here:"); // allocated by device, context - AI->AllocStack.Print(); + context.logger.always("{} is located inside of {} region [{}, {})", + (void *)Addr, ToString(AI->Type), + (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); + context.logger.always("allocated here:"); // allocated by device, context + AI->AllocStack.Print(); + + if (AI->IsReleased) { + context.logger.always("freed here:"); + AI->ReleaseStack.Print(); } + exit(1); } void ReportDoubleFree(uptr Addr, const StackTrace &Stack, - std::shared_ptr AI) { + const std::shared_ptr &AI) { context.logger.always("\n====ERROR: DeviceSanitizer: double-free on {}", (void *)Addr); Stack.Print(); @@ -80,8 +79,8 @@ void ReportDoubleFree(uptr Addr, const StackTrace &Stack, } void ReportGenericError(const DeviceSanitizerReport &Report, - ur_kernel_handle_t Kernel, ur_context_handle_t Context, - ur_device_handle_t Device) { + ur_kernel_handle_t Kernel, + ur_context_handle_t Context) { const char *File = Report.File[0] ? Report.File : ""; const char *Func = Report.Func[0] ? Report.Func : ""; auto KernelName = getKernelName(Kernel); @@ -101,25 +100,27 @@ void ReportGenericError(const DeviceSanitizerReport &Report, context.logger.always(" #0 {} {}:{}\n", Func, File, Report.Line); if (Report.ErrorType == DeviceSanitizerErrorType::USE_AFTER_FREE) { - auto AllocInfos = + auto AllocInfoItOp = context.interceptor->findAllocInfoByAddress(Report.Addr); - if (!AllocInfos.size()) { + if (!AllocInfoItOp) { context.logger.always("can't find which chunck {} is allocated", (void *)Report.Addr); } - for (auto &AllocInfo : AllocInfos) { - if (!AllocInfo->IsReleased) { - continue; - } - context.logger.always( - "{} is located inside of {} region [{}, {}]", - (void *)Report.Addr, ToString(AllocInfo->Type), - (void *)AllocInfo->UserBegin, (void *)AllocInfo->UserEnd); - context.logger.always("allocated by thread T0 here:"); - AllocInfo->AllocStack.Print(); - context.logger.always("released by thread T0 here:"); - AllocInfo->ReleaseStack.Print(); + auto &AllocInfo = (*AllocInfoItOp)->second; + if (AllocInfo->Context != Context) { + context.logger.always("can't find which chunck {} is allocated", + (void *)Report.Addr); } + assert(AllocInfo->IsReleased); + + context.logger.always("{} is located inside of {} region [{}, {}]", + (void *)Report.Addr, ToString(AllocInfo->Type), + (void *)AllocInfo->UserBegin, + (void *)AllocInfo->UserEnd); + context.logger.always("allocated by thread T0 here:"); + AllocInfo->AllocStack.Print(); + context.logger.always("released by thread T0 here:"); + AllocInfo->ReleaseStack.Print(); } exit(1); From 6e2b37dafac7bb5a9ff1cb5b7efad9c2b69e1f46 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sun, 3 Mar 2024 00:12:25 -0800 Subject: [PATCH 18/42] Use iterator to pass AllocInfo --- .../layers/sanitizer/asan_interceptor.hpp | 2 +- .../layers/sanitizer/asan_quarantine.hpp | 28 +++++++++---------- .../loader/layers/sanitizer/asan_report.hpp | 12 ++++---- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 057457e37d..5a663410c9 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -220,7 +220,7 @@ class SanitizerInterceptor { AllocationMap m_AllocationMap; ur_shared_mutex m_AllocationMapMutex; - uint32_t cl_Debug = 0; + uint64_t cl_Debug = 0; uint32_t cl_MaxQuarantineSizeMB = 0; std::unique_ptr m_Quarantine; diff --git a/source/loader/layers/sanitizer/asan_quarantine.hpp b/source/loader/layers/sanitizer/asan_quarantine.hpp index bed4728c9f..57b3144cfd 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.hpp +++ b/source/loader/layers/sanitizer/asan_quarantine.hpp @@ -24,34 +24,32 @@ namespace ur_sanitizer_layer { class QuarantineCache { public: + using Element = AllocationIterator; + using List = std::queue; + explicit QuarantineCache() {} // Total memory used, including internal accounting. uptr Size() const { return m_Size; } - // Memory used for internal accounting. - // uptr OverheadSize() const { return m_List.size() * sizeof(QuarantineBatch); } - - void Enqueue(std::shared_ptr &ptr) { - m_List.push(ptr); - m_Size += ptr->AllocSize; + void Enqueue(Element &It) { + m_List.push(It); + m_Size += It->second->AllocSize; } - std::shared_ptr Dequeue() { + std::optional Dequeue() { if (m_List.empty()) { - return nullptr; + return std::optional{}; } - auto b = m_List.front(); + auto It = m_List.front(); m_List.pop(); - m_Size -= b->AllocSize; - return b; + m_Size -= It->second->AllocSize; + return It; } void PrintStats() const {} private: - typedef std::queue> List; - List m_List; std::atomic_uintptr_t m_Size; }; @@ -61,8 +59,8 @@ class Quarantine { explicit Quarantine(size_t MaxQuarantineSize) : m_MaxQuarantineSize(MaxQuarantineSize) {} - std::vector> - put(ur_device_handle_t Device, std::shared_ptr &Ptr); + std::vector put(ur_device_handle_t Device, + AllocationIterator &Ptr); private: std::unordered_map m_Map; diff --git a/source/loader/layers/sanitizer/asan_report.hpp b/source/loader/layers/sanitizer/asan_report.hpp index ec1cdccc48..fba6802137 100644 --- a/source/loader/layers/sanitizer/asan_report.hpp +++ b/source/loader/layers/sanitizer/asan_report.hpp @@ -23,17 +23,15 @@ class AllocInfo; class StackTrace; void ReportBadFree(uptr Addr, const StackTrace &stack, - std::shared_ptr AllocInfo); + const std::shared_ptr &AllocInfo); -void ReportBadFreeContext( - uptr Addr, const StackTrace &stack, - const std::vector> &AllocInfos); +void ReportBadFreeContext(uptr Addr, const StackTrace &stack, + const std::shared_ptr &AllocInfos); void ReportDoubleFree(uptr Addr, const StackTrace &Stack, - std::shared_ptr AllocInfo); + const std::shared_ptr &AllocInfo); void ReportGenericError(const DeviceSanitizerReport &Report, - ur_kernel_handle_t Kernel, ur_context_handle_t Context, - ur_device_handle_t Device); + ur_kernel_handle_t Kernel, ur_context_handle_t Context); } // namespace ur_sanitizer_layer From 5de262469f818e0375161a064821e491098fcf06 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sun, 3 Mar 2024 18:15:25 -0800 Subject: [PATCH 19/42] wip --- .../layers/sanitizer/asan_interceptor.cpp | 32 +++++--- .../loader/layers/sanitizer/asan_report.cpp | 80 ++++++++++++------- .../loader/layers/sanitizer/asan_report.hpp | 7 +- .../layers/sanitizer/symbolizer_llvm.hpp | 2 + .../layers/sanitizer/ur_sanitizer_utils.cpp | 16 ++-- .../layers/sanitizer/ur_sanitizer_utils.hpp | 16 ++-- 6 files changed, 91 insertions(+), 62 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index f10771168b..f32a7638cf 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -222,7 +222,7 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, if (AllocInfo->Context != Context) { if (AllocInfo->UserBegin == Addr) { - ReportBadFreeContext(Addr, GetCurrentBacktrace(), AllocInfo); + ReportBadContext(Addr, GetCurrentBacktrace(), AllocInfo); } else { ReportBadFree(Addr, GetCurrentBacktrace(), nullptr); } @@ -267,8 +267,8 @@ ur_result_t SanitizerInterceptor::preLaunchKernel(ur_kernel_handle_t Kernel, ur_queue_handle_t Queue, LaunchInfo &LaunchInfo, uint32_t numWorkgroup) { - auto Context = getContext(Queue); - auto Device = getDevice(Queue); + auto Context = GetContext(Queue); + auto Device = GetDevice(Queue); auto ContextInfo = getContextInfo(Context); auto DeviceInfo = getDeviceInfo(Device); @@ -291,7 +291,7 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, ur_queue_handle_t Queue, ur_event_handle_t &Event, LaunchInfo &LaunchInfo) { - auto Program = getProgram(Kernel); + auto Program = GetProgram(Kernel); ur_event_handle_t ReadEvent{}; // If kernel has defined SPIR_DeviceSanitizerReportMem, then we try to read it @@ -306,10 +306,14 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, Event = ReadEvent; const auto &AH = LaunchInfo.SPIR_DeviceSanitizerReportMem; - if (AH.Flag) { + if (!AH.Flag) { return; } - ReportGenericError(AH, Kernel, getContext(Queue)); + if (AH.ErrorType == DeviceSanitizerErrorType::USE_AFTER_FREE) { + ReportUseAfterFree(AH, Kernel, GetContext(Queue)); + } else { + ReportGenericError(AH, Kernel); + } } } @@ -532,7 +536,7 @@ ur_result_t SanitizerInterceptor::updateShadowMemory( ur_result_t SanitizerInterceptor::registerDeviceGlobals(ur_context_handle_t Context, ur_program_handle_t Program) { - std::vector Devices = getProgramDevices(Program); + std::vector Devices = GetProgramDevices(Program); auto ContextInfo = getContextInfo(Context); @@ -622,7 +626,7 @@ SanitizerInterceptor::insertDevice(ur_device_handle_t Device, DI = std::make_shared(Device); // Query device type - DI->Type = getDeviceType(Device); + DI->Type = GetDeviceType(Device); if (DI->Type == DeviceType::UNKNOWN) { return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; } @@ -649,7 +653,7 @@ ur_result_t SanitizerInterceptor::prepareLaunch( ur_context_handle_t Context, std::shared_ptr &DeviceInfo, ur_queue_handle_t Queue, ur_kernel_handle_t Kernel, LaunchInfo &LaunchInfo, uint32_t numWorkgroup) { - auto Program = getProgram(Kernel); + auto Program = GetProgram(Kernel); do { // Set global variable to program @@ -687,7 +691,7 @@ ur_result_t SanitizerInterceptor::prepareLaunch( } // Write shadow memory offset for local memory - auto LocalMemorySize = getLocalMemorySize(DeviceInfo->Handle); + auto LocalMemorySize = GetLocalMemorySize(DeviceInfo->Handle); auto LocalShadowMemorySize = (numWorkgroup * LocalMemorySize) >> ASAN_SHADOW_SCALE; @@ -740,9 +744,11 @@ ur_result_t SanitizerInterceptor::prepareLaunch( std::optional SanitizerInterceptor::findAllocInfoByAddress(uptr Address) { std::shared_lock Guard(m_AllocationMapMutex); - auto It = m_AllocationMap.lower_bound(Address); - return It == m_AllocationMap.end() ? std::optional{} - : It; + auto It = m_AllocationMap.upper_bound(Address); + if (It == m_AllocationMap.begin()) { + return std::optional{}; + } + return --It; } LaunchInfo::~LaunchInfo() { diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index 496f60854d..521a14e850 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -42,10 +42,10 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, exit(1); } -void ReportBadFreeContext(uptr Addr, const StackTrace &stack, - const std::shared_ptr &AI) { - context.logger.always( - "\n====ERROR: DeviceSanitizer: bad-free-context on {}", (void *)Addr); +void ReportBadContext(uptr Addr, const StackTrace &stack, + const std::shared_ptr &AI) { + context.logger.always("\n====ERROR: DeviceSanitizer: bad-context on {}", + (void *)Addr); stack.Print(); context.logger.always("{} is located inside of {} region [{}, {})", @@ -79,11 +79,10 @@ void ReportDoubleFree(uptr Addr, const StackTrace &Stack, } void ReportGenericError(const DeviceSanitizerReport &Report, - ur_kernel_handle_t Kernel, - ur_context_handle_t Context) { + ur_kernel_handle_t Kernel) { const char *File = Report.File[0] ? Report.File : ""; const char *Func = Report.Func[0] ? Report.Func : ""; - auto KernelName = getKernelName(Kernel); + auto KernelName = GetKernelName(Kernel); // Try to demangle the kernel name KernelName = DemangleName(KernelName); @@ -97,31 +96,50 @@ void ReportGenericError(const DeviceSanitizerReport &Report, Report.IsWrite ? "WRITE" : "READ", Report.AccessSize, KernelName.c_str(), Report.LID0, Report.LID1, Report.LID2, Report.GID0, Report.GID1, Report.GID2); - context.logger.always(" #0 {} {}:{}\n", Func, File, Report.Line); - - if (Report.ErrorType == DeviceSanitizerErrorType::USE_AFTER_FREE) { - auto AllocInfoItOp = - context.interceptor->findAllocInfoByAddress(Report.Addr); - if (!AllocInfoItOp) { - context.logger.always("can't find which chunck {} is allocated", - (void *)Report.Addr); - } - auto &AllocInfo = (*AllocInfoItOp)->second; - if (AllocInfo->Context != Context) { - context.logger.always("can't find which chunck {} is allocated", - (void *)Report.Addr); - } - assert(AllocInfo->IsReleased); - - context.logger.always("{} is located inside of {} region [{}, {}]", - (void *)Report.Addr, ToString(AllocInfo->Type), - (void *)AllocInfo->UserBegin, - (void *)AllocInfo->UserEnd); - context.logger.always("allocated by thread T0 here:"); - AllocInfo->AllocStack.Print(); - context.logger.always("released by thread T0 here:"); - AllocInfo->ReleaseStack.Print(); + context.logger.always(" #0 {} {}:{}", Func, File, Report.Line); + + exit(1); +} + +void ReportUseAfterFree(const DeviceSanitizerReport &Report, + ur_kernel_handle_t Kernel, + ur_context_handle_t Context) { + const char *File = Report.File[0] ? Report.File : ""; + const char *Func = Report.Func[0] ? Report.Func : ""; + auto KernelName = GetKernelName(Kernel); + + // Try to demangle the kernel name + KernelName = DemangleName(KernelName); + + context.logger.always("\n====ERROR: DeviceSanitizer: {} on {}", + ToString(Report.ErrorType), (void *)Report.Addr); + context.logger.always( + "{} of size {} at kernel <{}> LID({}, {}, {}) GID({}, " + "{}, {})", + Report.IsWrite ? "WRITE" : "READ", Report.AccessSize, + KernelName.c_str(), Report.LID0, Report.LID1, Report.LID2, Report.GID0, + Report.GID1, Report.GID2); + context.logger.always(" #0 {} {}:{}", Func, File, Report.Line); + context.logger.always(""); + + auto AllocInfoItOp = + context.interceptor->findAllocInfoByAddress(Report.Addr); + auto &AllocInfo = (*AllocInfoItOp)->second; + + if (!AllocInfoItOp || AllocInfo->Context != Context) { + context.logger.always("Failed to find which chunck {} is allocated", + (void *)Report.Addr); } + assert(AllocInfo->IsReleased); + + context.logger.always("{} is located inside of {} region [{}, {})", + (void *)Report.Addr, ToString(AllocInfo->Type), + (void *)AllocInfo->UserBegin, + (void *)(AllocInfo->UserEnd + 1)); + context.logger.always("allocated here:"); + AllocInfo->AllocStack.Print(); + context.logger.always("released here:"); + AllocInfo->ReleaseStack.Print(); exit(1); } diff --git a/source/loader/layers/sanitizer/asan_report.hpp b/source/loader/layers/sanitizer/asan_report.hpp index fba6802137..ec49471603 100644 --- a/source/loader/layers/sanitizer/asan_report.hpp +++ b/source/loader/layers/sanitizer/asan_report.hpp @@ -25,13 +25,16 @@ class StackTrace; void ReportBadFree(uptr Addr, const StackTrace &stack, const std::shared_ptr &AllocInfo); -void ReportBadFreeContext(uptr Addr, const StackTrace &stack, - const std::shared_ptr &AllocInfos); +void ReportBadContext(uptr Addr, const StackTrace &stack, + const std::shared_ptr &AllocInfos); void ReportDoubleFree(uptr Addr, const StackTrace &Stack, const std::shared_ptr &AllocInfo); void ReportGenericError(const DeviceSanitizerReport &Report, + ur_kernel_handle_t Kernel); + +void ReportUseAfterFree(const DeviceSanitizerReport &Report, ur_kernel_handle_t Kernel, ur_context_handle_t Context); } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.hpp b/source/loader/layers/sanitizer/symbolizer_llvm.hpp index 23ec756e3d..1e2864628e 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.hpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.hpp @@ -18,6 +18,8 @@ namespace ur_sanitizer_layer { class SymbolizerTool { virtual bool SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { + std::ignore = BI; + std::ignore = SI; return false; } }; diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp index 00864837dd..271fc58ecc 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp @@ -15,7 +15,7 @@ namespace ur_sanitizer_layer { -ur_context_handle_t getContext(ur_queue_handle_t Queue) { +ur_context_handle_t GetContext(ur_queue_handle_t Queue) { ur_context_handle_t Context{}; [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( Queue, UR_QUEUE_INFO_CONTEXT, sizeof(ur_context_handle_t), &Context, @@ -24,7 +24,7 @@ ur_context_handle_t getContext(ur_queue_handle_t Queue) { return Context; } -ur_device_handle_t getDevice(ur_queue_handle_t Queue) { +ur_device_handle_t GetDevice(ur_queue_handle_t Queue) { ur_device_handle_t Device{}; [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( Queue, UR_QUEUE_INFO_DEVICE, sizeof(ur_device_handle_t), &Device, @@ -33,7 +33,7 @@ ur_device_handle_t getDevice(ur_queue_handle_t Queue) { return Device; } -ur_program_handle_t getProgram(ur_kernel_handle_t Kernel) { +ur_program_handle_t GetProgram(ur_kernel_handle_t Kernel) { ur_program_handle_t Program{}; [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( Kernel, UR_KERNEL_INFO_PROGRAM, sizeof(ur_program_handle_t), &Program, @@ -42,7 +42,7 @@ ur_program_handle_t getProgram(ur_kernel_handle_t Kernel) { return Program; } -size_t getLocalMemorySize(ur_device_handle_t Device) { +size_t GetLocalMemorySize(ur_device_handle_t Device) { size_t LocalMemorySize{}; [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( Device, UR_DEVICE_INFO_LOCAL_MEM_SIZE, sizeof(LocalMemorySize), @@ -51,7 +51,7 @@ size_t getLocalMemorySize(ur_device_handle_t Device) { return LocalMemorySize; } -std::string getKernelName(ur_kernel_handle_t Kernel) { +std::string GetKernelName(ur_kernel_handle_t Kernel) { size_t KernelNameSize = 0; [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( Kernel, UR_KERNEL_INFO_FUNCTION_NAME, 0, nullptr, &KernelNameSize); @@ -66,7 +66,7 @@ std::string getKernelName(ur_kernel_handle_t Kernel) { return std::string(KernelNameBuf.data(), KernelNameSize - 1); } -ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, +ur_device_handle_t GetUSMAllocDevice(ur_context_handle_t Context, const void *MemPtr) { ur_device_handle_t Device{}; // if urGetMemAllocInfo failed, return nullptr @@ -76,7 +76,7 @@ ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, return Device; } -DeviceType getDeviceType(ur_device_handle_t Device) { +DeviceType GetDeviceType(ur_device_handle_t Device) { ur_device_type_t DeviceType = UR_DEVICE_TYPE_DEFAULT; [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnGetInfo( Device, UR_DEVICE_INFO_TYPE, sizeof(DeviceType), &DeviceType, nullptr); @@ -93,7 +93,7 @@ DeviceType getDeviceType(ur_device_handle_t Device) { } } -std::vector getProgramDevices(ur_program_handle_t Program) { +std::vector GetProgramDevices(ur_program_handle_t Program) { size_t PropSize; [[maybe_unused]] ur_result_t Result = context.urDdiTable.Program.pfnGetInfo( Program, UR_PROGRAM_INFO_DEVICES, 0, nullptr, &PropSize); diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp index f80e46cb9c..339a26d377 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp @@ -16,14 +16,14 @@ namespace ur_sanitizer_layer { -ur_context_handle_t getContext(ur_queue_handle_t Queue); -ur_device_handle_t getDevice(ur_queue_handle_t Queue); -ur_program_handle_t getProgram(ur_kernel_handle_t Kernel); -size_t getLocalMemorySize(ur_device_handle_t Device); -std::string getKernelName(ur_kernel_handle_t Kernel); -ur_device_handle_t getUSMAllocDevice(ur_context_handle_t Context, +ur_context_handle_t GetContext(ur_queue_handle_t Queue); +ur_device_handle_t GetDevice(ur_queue_handle_t Queue); +ur_program_handle_t GetProgram(ur_kernel_handle_t Kernel); +size_t GetLocalMemorySize(ur_device_handle_t Device); +std::string GetKernelName(ur_kernel_handle_t Kernel); +ur_device_handle_t GetUSMAllocDevice(ur_context_handle_t Context, const void *MemPtr); -DeviceType getDeviceType(ur_device_handle_t Device); -std::vector getProgramDevices(ur_program_handle_t Program); +DeviceType GetDeviceType(ur_device_handle_t Device); +std::vector GetProgramDevices(ur_program_handle_t Program); } // namespace ur_sanitizer_layer From afe24fe5339f454361bf47fe0b297bcd3c61409a Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sun, 3 Mar 2024 19:47:15 -0800 Subject: [PATCH 20/42] wip --- .../layers/sanitizer/asan_interceptor.cpp | 34 +++++++++++++------ .../layers/sanitizer/asan_interceptor.hpp | 1 + .../layers/sanitizer/asan_quarantine.cpp | 8 ++--- .../layers/sanitizer/asan_quarantine.hpp | 2 +- .../loader/layers/sanitizer/asan_report.cpp | 16 +++++---- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index f32a7638cf..e9aae387ee 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -103,7 +103,8 @@ SanitizerInterceptor::SanitizerInterceptor() { cl_MaxQuarantineSizeMB = std::stoul(Value); } if (cl_MaxQuarantineSizeMB) { - m_Quarantine = std::make_unique(cl_MaxQuarantineSizeMB); + m_Quarantine = + std::make_unique(cl_MaxQuarantineSizeMB * 1024); } } @@ -194,7 +195,7 @@ ur_result_t SanitizerInterceptor::allocateMemory( } context.logger.info( - "AllocInfos(AllocBegin={}, User={}-{}, NeededSize={}, Type={})", + "AllocInfo(AllocBegin={}, User={}-{}, NeededSize={}, Type={})", (void *)AllocBegin, (void *)UserBegin, (void *)UserEnd, NeededSize, ToString(Type)); @@ -209,6 +210,7 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, auto AllocInfoItOp = findAllocInfoByAddress(Addr); if (!AllocInfoItOp) { + // "Addr" might be a host pointer ReportBadFree(Addr, GetCurrentBacktrace(), nullptr); return UR_RESULT_ERROR_INVALID_ARGUMENT; } @@ -224,6 +226,7 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, if (AllocInfo->UserBegin == Addr) { ReportBadContext(Addr, GetCurrentBacktrace(), AllocInfo); } else { + // "Addr" might be a host pointer ReportBadFree(Addr, GetCurrentBacktrace(), nullptr); } return UR_RESULT_ERROR_INVALID_ARGUMENT; @@ -242,24 +245,33 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, AllocInfo->IsReleased = true; AllocInfo->ReleaseStack = GetCurrentBacktrace(); - auto Device = AllocInfo->Device; + if (AllocInfo->Type == AllocType::HOST_USM) { + ContextInfo->insertAllocInfo(ContextInfo->DeviceList, AllocInfo); + } else { + ContextInfo->insertAllocInfo({AllocInfo->Device}, AllocInfo); + } + + // If quarantine is disabled, USM is freed immediately + if (!m_Quarantine) { + context.logger.debug("Free: {}", (void *)AllocInfo->AllocBegin); + std::scoped_lock Guard(m_AllocationMapMutex); + m_AllocationMap.erase(AllocInfoIt); + return context.urDdiTable.USM.pfnFree(Context, + (void *)(AllocInfo->AllocBegin)); + } - if (m_Quarantine) { - auto ReleaseList = m_Quarantine->put(Device, AllocInfoIt); + auto ReleaseList = m_Quarantine->put(AllocInfo->Device, AllocInfoIt); + if (ReleaseList.size()) { std::scoped_lock Guard(m_AllocationMapMutex); for (auto &It : ReleaseList) { + context.logger.info("Quarantine Free: {}", + (void *)It->second->AllocBegin); context.urDdiTable.USM.pfnFree(Context, (void *)(It->second->AllocBegin)); m_AllocationMap.erase(It); } } - if (AllocInfo->Type == AllocType::HOST_USM) { - ContextInfo->insertAllocInfo(ContextInfo->DeviceList, AllocInfo); - } else { - ContextInfo->insertAllocInfo({Device}, AllocInfo); - } - return UR_RESULT_SUCCESS; } diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 5a663410c9..09ae4837b5 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -217,6 +217,7 @@ class SanitizerInterceptor { m_DeviceMap; ur_shared_mutex m_DeviceMapMutex; + /// Assumption: all usm chunks are allocated in one VA AllocationMap m_AllocationMap; ur_shared_mutex m_AllocationMapMutex; diff --git a/source/loader/layers/sanitizer/asan_quarantine.cpp b/source/loader/layers/sanitizer/asan_quarantine.cpp index 99e3d6173b..b2d7d2d123 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.cpp +++ b/source/loader/layers/sanitizer/asan_quarantine.cpp @@ -21,13 +21,13 @@ std::vector Quarantine::put(ur_device_handle_t Device, auto &Cache = m_Map[Device]; std::vector DequeueList; while (Cache.Size() + AllocSize > m_MaxQuarantineSize) { - auto ItOp = Cache.Dequeue(); - if (!ItOp) { + auto ElementOp = Cache.Dequeue(); + if (!ElementOp) { break; } - DequeueList.emplace_back(*ItOp); + DequeueList.emplace_back(*ElementOp); } - m_Map[Device].Enqueue(It); + Cache.Enqueue(It); return DequeueList; } diff --git a/source/loader/layers/sanitizer/asan_quarantine.hpp b/source/loader/layers/sanitizer/asan_quarantine.hpp index 57b3144cfd..06c64464c8 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.hpp +++ b/source/loader/layers/sanitizer/asan_quarantine.hpp @@ -51,7 +51,7 @@ class QuarantineCache { private: List m_List; - std::atomic_uintptr_t m_Size; + std::atomic_uintptr_t m_Size = 0; }; class Quarantine { diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index 521a14e850..7707972b97 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -21,8 +21,8 @@ namespace ur_sanitizer_layer { void ReportBadFree(uptr Addr, const StackTrace &stack, const std::shared_ptr &AI) { - context.logger.always("\n====ERROR: DeviceSanitizer: bad-free on {}", - (void *)Addr); + context.logger.always( + "\n====ERROR: DeviceSanitizer: bad-free on address {}", (void *)Addr); stack.Print(); if (!AI) { // maybe Addr is host allocated memory @@ -44,8 +44,9 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, void ReportBadContext(uptr Addr, const StackTrace &stack, const std::shared_ptr &AI) { - context.logger.always("\n====ERROR: DeviceSanitizer: bad-context on {}", - (void *)Addr); + context.logger.always( + "\n====ERROR: DeviceSanitizer: bad-context on address {}", + (void *)Addr); stack.Print(); context.logger.always("{} is located inside of {} region [{}, {})", @@ -64,8 +65,9 @@ void ReportBadContext(uptr Addr, const StackTrace &stack, void ReportDoubleFree(uptr Addr, const StackTrace &Stack, const std::shared_ptr &AI) { - context.logger.always("\n====ERROR: DeviceSanitizer: double-free on {}", - (void *)Addr); + context.logger.always( + "\n====ERROR: DeviceSanitizer: double-free on address {}", + (void *)Addr); Stack.Print(); context.logger.always("{} is located inside of {} region [{}, {})", @@ -111,7 +113,7 @@ void ReportUseAfterFree(const DeviceSanitizerReport &Report, // Try to demangle the kernel name KernelName = DemangleName(KernelName); - context.logger.always("\n====ERROR: DeviceSanitizer: {} on {}", + context.logger.always("\n====ERROR: DeviceSanitizer: {} on address {}", ToString(Report.ErrorType), (void *)Report.Addr); context.logger.always( "{} of size {} at kernel <{}> LID({}, {}, {}) GID({}, " From 31a36d874e5b7dd492ab0e0cba17d60c4ab57723 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sun, 3 Mar 2024 19:49:39 -0800 Subject: [PATCH 21/42] wip --- source/loader/layers/sanitizer/asan_interceptor.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 09ae4837b5..14cbbceec2 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -20,9 +20,7 @@ #include #include #include -#include #include -#include #include namespace ur_sanitizer_layer { @@ -46,7 +44,7 @@ struct DeviceInfo { std::queue> Quarantine; size_t QuarantineSize = 0; - DeviceInfo(ur_device_handle_t Device) : Handle(Device) { + explicit DeviceInfo(ur_device_handle_t Device) : Handle(Device) { [[maybe_unused]] auto Result = context.urDdiTable.Device.pfnRetain(Device); assert(Result == UR_RESULT_SUCCESS); @@ -66,7 +64,8 @@ struct QueueInfo { ur_mutex Mutex; ur_event_handle_t LastEvent; - QueueInfo(ur_queue_handle_t Queue) : Handle(Queue), LastEvent(nullptr) { + explicit QueueInfo(ur_queue_handle_t Queue) + : Handle(Queue), LastEvent(nullptr) { [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnRetain(Queue); assert(Result == UR_RESULT_SUCCESS); @@ -94,7 +93,7 @@ struct ContextInfo { std::vector DeviceList; std::unordered_map AllocInfosMap; - ContextInfo(ur_context_handle_t Context) : Handle(Context) { + explicit ContextInfo(ur_context_handle_t Context) : Handle(Context) { [[maybe_unused]] auto Result = context.urDdiTable.Context.pfnRetain(Context); assert(Result == UR_RESULT_SUCCESS); From 56cf58ca6d1ad4b2957d092530c2ae910fc680f9 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sun, 3 Mar 2024 22:01:24 -0800 Subject: [PATCH 22/42] fix reviews --- .../layers/sanitizer/asan_allocator.cpp | 8 ++++++++ .../layers/sanitizer/asan_allocator.hpp | 2 ++ .../layers/sanitizer/linux/backtrace.cpp | 6 +++++- source/loader/layers/sanitizer/stacktrace.cpp | 20 ++++++++++--------- source/loader/layers/sanitizer/stacktrace.hpp | 4 ++-- .../layers/sanitizer/symbolizer_llvm.cpp | 2 +- .../layers/sanitizer/symbolizer_llvm.hpp | 2 +- .../layers/sanitizer/ur_sanitizer_utils.cpp | 2 +- .../layers/sanitizer/ur_sanitizer_utils.hpp | 2 +- 9 files changed, 32 insertions(+), 16 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_allocator.cpp b/source/loader/layers/sanitizer/asan_allocator.cpp index f6fe9f903d..a6d5c8fda6 100644 --- a/source/loader/layers/sanitizer/asan_allocator.cpp +++ b/source/loader/layers/sanitizer/asan_allocator.cpp @@ -11,7 +11,15 @@ */ #include "asan_allocator.hpp" +#include "ur_sanitizer_layer.hpp" namespace ur_sanitizer_layer { +void AllocInfo::Print() { + context.logger.info( + "AllocInfo(AllocBegin={}, User={}-{}, NeededSize={}, Type={})", + (void *)AllocBegin, (void *)UserBegin, (void *)UserEnd, AllocSize, + ToString(Type)); +} + } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_allocator.hpp b/source/loader/layers/sanitizer/asan_allocator.hpp index c7cf89c2ba..c2ba9819d0 100644 --- a/source/loader/layers/sanitizer/asan_allocator.hpp +++ b/source/loader/layers/sanitizer/asan_allocator.hpp @@ -42,6 +42,8 @@ struct AllocInfo { StackTrace AllocStack; StackTrace ReleaseStack; + + void Print(); }; using AllocationMap = std::map>; diff --git a/source/loader/layers/sanitizer/linux/backtrace.cpp b/source/loader/layers/sanitizer/linux/backtrace.cpp index b31fab3300..3a50c09655 100644 --- a/source/loader/layers/sanitizer/linux/backtrace.cpp +++ b/source/loader/layers/sanitizer/linux/backtrace.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2024 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. * See LICENSE.TXT @@ -15,6 +15,8 @@ namespace ur_sanitizer_layer { +namespace { + bool ExtractSymbolInfo(const char *symbol, BacktraceInfo &info) { info.debug = std::string(symbol); @@ -25,6 +27,8 @@ bool ExtractSymbolInfo(const char *symbol, BacktraceInfo &info) { return true; } +} // namespace + StackTrace GetCurrentBacktrace() { void *backtraceFrames[MAX_BACKTRACE_FRAMES]; int frameCount = backtrace(backtraceFrames, MAX_BACKTRACE_FRAMES); diff --git a/source/loader/layers/sanitizer/stacktrace.cpp b/source/loader/layers/sanitizer/stacktrace.cpp index b4e4b9635b..47ad51ba8f 100644 --- a/source/loader/layers/sanitizer/stacktrace.cpp +++ b/source/loader/layers/sanitizer/stacktrace.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2024 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. * See LICENSE.TXT @@ -18,17 +18,19 @@ namespace ur_sanitizer_layer { -#define MAX_BACKTRACE_FRAMES 64 +namespace { -std::string getFileName(const std::string &FilePath) { +std::string GetFileName(const std::string &FilePath) { auto p = FilePath.find_last_of('/'); return FilePath.substr(p + 1); } -bool startWith(const std::string &Str, const char *Pattern) { +bool StartWith(const std::string &Str, const char *Pattern) { return Str.rfind(Pattern, 0) == 0; } +} // namespace + void StackTrace::Print() const { if (!stack.size()) { context.logger.always(" failed to acquire backtrace"); @@ -38,10 +40,10 @@ void StackTrace::Print() const { unsigned index = 0; for (auto &BI : stack) { - auto ModuleFile = getFileName(BI.module); - if (startWith(ModuleFile, "libsycl.so") || - startWith(ModuleFile, "libpi_unified_runtime.so") || - startWith(ModuleFile, "libur_loader.so")) { + auto ModuleFile = GetFileName(BI.module); + if (StartWith(ModuleFile, "libsycl.so") || + StartWith(ModuleFile, "libpi_unified_runtime.so") || + StartWith(ModuleFile, "libur_loader.so")) { continue; } @@ -61,4 +63,4 @@ void StackTrace::Print() const { context.logger.always(""); } -} // namespace ur_sanitizer_layer \ No newline at end of file +} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/stacktrace.hpp b/source/loader/layers/sanitizer/stacktrace.hpp index 2c6eb6f756..4af6328560 100644 --- a/source/loader/layers/sanitizer/stacktrace.hpp +++ b/source/loader/layers/sanitizer/stacktrace.hpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2024 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. * See LICENSE.TXT @@ -18,7 +18,7 @@ namespace ur_sanitizer_layer { -#define MAX_BACKTRACE_FRAMES 64 +constexpr size_t MAX_BACKTRACE_FRAMES = 64; struct StackTrace { std::vector stack; diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.cpp b/source/loader/layers/sanitizer/symbolizer_llvm.cpp index 5c4a34f6c8..1893b25f6c 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.cpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2024 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. * See LICENSE.TXT diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.hpp b/source/loader/layers/sanitizer/symbolizer_llvm.hpp index 1e2864628e..11bf3e99a8 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.hpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.hpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2024 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. * See LICENSE.TXT diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp index 271fc58ecc..67d5b6ee88 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2024 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. * See LICENSE.TXT diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp index 339a26d377..852d59314a 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2024 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. * See LICENSE.TXT From afd69107ba9b8d11794d12b690e898967c426ea5 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sun, 3 Mar 2024 22:07:12 -0800 Subject: [PATCH 23/42] fix CI --- source/loader/layers/sanitizer/asan_interceptor.cpp | 9 +-------- source/loader/layers/sanitizer/asan_report.hpp | 6 +++--- source/loader/layers/sanitizer/stacktrace.cpp | 2 -- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index e9aae387ee..e47e2e1a53 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -194,10 +194,7 @@ ur_result_t SanitizerInterceptor::allocateMemory( m_AllocationMap.emplace(AI->AllocBegin, std::move(AI)); } - context.logger.info( - "AllocInfo(AllocBegin={}, User={}-{}, NeededSize={}, Type={})", - (void *)AllocBegin, (void *)UserBegin, (void *)UserEnd, NeededSize, - ToString(Type)); + AI->Print(); return UR_RESULT_SUCCESS; } @@ -218,10 +215,6 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, auto AllocInfoIt = *AllocInfoItOp; auto &AllocInfo = AllocInfoIt->second; - context.logger.debug("AllocInfo(AllocBegin={}, UserBegin={})", - (void *)AllocInfo->AllocBegin, - (void *)AllocInfo->UserBegin); - if (AllocInfo->Context != Context) { if (AllocInfo->UserBegin == Addr) { ReportBadContext(Addr, GetCurrentBacktrace(), AllocInfo); diff --git a/source/loader/layers/sanitizer/asan_report.hpp b/source/loader/layers/sanitizer/asan_report.hpp index ec49471603..e1ac7daacf 100644 --- a/source/loader/layers/sanitizer/asan_report.hpp +++ b/source/loader/layers/sanitizer/asan_report.hpp @@ -18,9 +18,9 @@ namespace ur_sanitizer_layer { -class DeviceSanitizerReport; -class AllocInfo; -class StackTrace; +struct DeviceSanitizerReport; +struct AllocInfo; +struct StackTrace; void ReportBadFree(uptr Addr, const StackTrace &stack, const std::shared_ptr &AllocInfo); diff --git a/source/loader/layers/sanitizer/stacktrace.cpp b/source/loader/layers/sanitizer/stacktrace.cpp index 47ad51ba8f..ac7c500a5f 100644 --- a/source/loader/layers/sanitizer/stacktrace.cpp +++ b/source/loader/layers/sanitizer/stacktrace.cpp @@ -10,8 +10,6 @@ * */ -#pragma once - #include "stacktrace.hpp" #include "symbolizer_llvm.hpp" #include "ur_sanitizer_layer.hpp" From 5a0781c37344b1236b06fd4111a30a6355dac52a Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sun, 3 Mar 2024 22:27:55 -0800 Subject: [PATCH 24/42] fix comments --- source/loader/layers/sanitizer/asan_allocator.cpp | 2 +- source/loader/layers/sanitizer/asan_interceptor.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_allocator.cpp b/source/loader/layers/sanitizer/asan_allocator.cpp index a6d5c8fda6..de332a40ec 100644 --- a/source/loader/layers/sanitizer/asan_allocator.cpp +++ b/source/loader/layers/sanitizer/asan_allocator.cpp @@ -17,7 +17,7 @@ namespace ur_sanitizer_layer { void AllocInfo::Print() { context.logger.info( - "AllocInfo(AllocBegin={}, User={}-{}, NeededSize={}, Type={})", + "AllocInfo(AllocBegin={}, User={}-{}, AllocSize={}, Type={})", (void *)AllocBegin, (void *)UserBegin, (void *)UserEnd, AllocSize, ToString(Type)); } diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index e47e2e1a53..6385a9515b 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -181,6 +181,8 @@ ur_result_t SanitizerInterceptor::allocateMemory( GetCurrentBacktrace(), {}}); + AI->Print(); + // For updating shadow memory if (Device) { // Device/Shared USM ContextInfo->insertAllocInfo({Device}, AI); @@ -194,8 +196,6 @@ ur_result_t SanitizerInterceptor::allocateMemory( m_AllocationMap.emplace(AI->AllocBegin, std::move(AI)); } - AI->Print(); - return UR_RESULT_SUCCESS; } From 84d58251e54705da6ee452cf021dcd68bf12ca0b Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Mon, 4 Mar 2024 00:02:39 -0800 Subject: [PATCH 25/42] check llvm-symbolizer --- .../layers/sanitizer/asan_quarantine.hpp | 1 - source/loader/layers/sanitizer/stacktrace.cpp | 7 +++++-- .../layers/sanitizer/symbolizer_llvm.cpp | 20 ++++++++++++++++++- .../layers/sanitizer/symbolizer_llvm.hpp | 7 +++++++ source/loader/layers/sanitizer/ur_sanddi.cpp | 3 +++ 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_quarantine.hpp b/source/loader/layers/sanitizer/asan_quarantine.hpp index 06c64464c8..fb2d293082 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.hpp +++ b/source/loader/layers/sanitizer/asan_quarantine.hpp @@ -15,7 +15,6 @@ #include "asan_allocator.hpp" #include -#include #include #include #include diff --git a/source/loader/layers/sanitizer/stacktrace.cpp b/source/loader/layers/sanitizer/stacktrace.cpp index ac7c500a5f..b1ad371839 100644 --- a/source/loader/layers/sanitizer/stacktrace.cpp +++ b/source/loader/layers/sanitizer/stacktrace.cpp @@ -34,7 +34,6 @@ void StackTrace::Print() const { context.logger.always(" failed to acquire backtrace"); } - LLVMSymbolizer symbolizer; unsigned index = 0; for (auto &BI : stack) { @@ -46,7 +45,11 @@ void StackTrace::Print() const { } SourceInfo SI; - symbolizer.SymbolizePC(BI, SI); + for (auto &symbolizer : SymbolizerTools) { + if (symbolizer->SymbolizePC(BI, SI)) { + break; + } + } if (!SI.file.empty()) { context.logger.always(" #{} {} in {} {}:{}:{}", index, diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.cpp b/source/loader/layers/sanitizer/symbolizer_llvm.cpp index 1893b25f6c..260fe17318 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.cpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.cpp @@ -11,12 +11,17 @@ */ #include "symbolizer_llvm.hpp" +#include "ur_sanitizer_layer.hpp" #include #include namespace ur_sanitizer_layer { +std::vector> SymbolizerTools; + +namespace { + bool ExtractSourceInfo(const std::string &output, SourceInfo &SI) { auto p1 = output.find('\n'); std::string function = output.substr(0, p1); @@ -36,13 +41,26 @@ bool ExtractSourceInfo(const std::string &output, SourceInfo &SI) { return true; } +} // namespace + bool LLVMSymbolizer::SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { std::stringstream ss; ss << "llvm-symbolizer --obj=" << BI.module << " " << BI.offset; auto result = RunCommand(ss.str().c_str()); - // context.logger.debug("llvm-symbolizer: {}", result); ExtractSourceInfo(result, SI); return true; } +void InitSymbolizers() { + auto result = RunCommand("llvm-symbolizer -v"); + if (result.size()) { + SymbolizerTools.emplace_back(std::make_unique()); + } + + if (SymbolizerTools.empty()) { + context.logger.always("[WARNING]: llvm-symbolizer is needed " + "for UR_LAYER_ASAN"); + } +} + } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.hpp b/source/loader/layers/sanitizer/symbolizer_llvm.hpp index 11bf3e99a8..32afb903e0 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.hpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.hpp @@ -14,9 +14,13 @@ #include "common.hpp" +#include +#include + namespace ur_sanitizer_layer { class SymbolizerTool { + public: virtual bool SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { std::ignore = BI; std::ignore = SI; @@ -29,4 +33,7 @@ class LLVMSymbolizer final : public SymbolizerTool { bool SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) override; }; +extern std::vector> SymbolizerTools; +void InitSymbolizers(); + } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index c9b5577b1a..4c7609ba36 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -11,6 +11,7 @@ */ #include "asan_interceptor.hpp" +#include "symbolizer_llvm.hpp" #include "ur_sanitizer_layer.hpp" namespace ur_sanitizer_layer { @@ -483,6 +484,8 @@ ur_result_t context_t::init(ur_dditable_t *dditable, UR_API_VERSION_CURRENT, &dditable->USM); } + InitSymbolizers(); + return result; } From e07c64b6874fb56a5805eef65c6a9eebd49521af Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Mon, 4 Mar 2024 00:48:05 -0800 Subject: [PATCH 26/42] fix ci --- source/loader/CMakeLists.txt | 2 -- source/loader/layers/sanitizer/asan_interceptor.cpp | 5 +++-- source/loader/layers/sanitizer/asan_report.cpp | 13 +++++++++---- source/loader/layers/sanitizer/symbolizer_llvm.hpp | 1 + source/loader/layers/sanitizer/ur_sanddi.cpp | 2 -- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/source/loader/CMakeLists.txt b/source/loader/CMakeLists.txt index 1f3705eeaa..d17764a6e2 100644 --- a/source/loader/CMakeLists.txt +++ b/source/loader/CMakeLists.txt @@ -115,8 +115,6 @@ if(UR_ENABLE_SANITIZER) ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_report.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_report.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/common.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/device_sanitizer_report.hpp diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 6385a9515b..f6d02508f3 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -259,9 +259,9 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, for (auto &It : ReleaseList) { context.logger.info("Quarantine Free: {}", (void *)It->second->AllocBegin); - context.urDdiTable.USM.pfnFree(Context, - (void *)(It->second->AllocBegin)); m_AllocationMap.erase(It); + UR_CALL(context.urDdiTable.USM.pfnFree( + Context, (void *)(It->second->AllocBegin))); } } @@ -279,6 +279,7 @@ ur_result_t SanitizerInterceptor::preLaunchKernel(ur_kernel_handle_t Kernel, ManagedQueue InternalQueue(Context, Device); if (!InternalQueue) { + context.logger.error("Failed to create internal queue"); return UR_RESULT_ERROR_INVALID_QUEUE; } diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index 7707972b97..5391d3ad16 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -25,7 +25,7 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, "\n====ERROR: DeviceSanitizer: bad-free on address {}", (void *)Addr); stack.Print(); - if (!AI) { // maybe Addr is host allocated memory + if (!AI) { context.logger.always("{} may be allocated on Host Memory", (void *)Addr); exit(1); @@ -52,7 +52,7 @@ void ReportBadContext(uptr Addr, const StackTrace &stack, context.logger.always("{} is located inside of {} region [{}, {})", (void *)Addr, ToString(AI->Type), (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); - context.logger.always("allocated here:"); // allocated by device, context + context.logger.always("allocated here:"); AI->AllocStack.Print(); if (AI->IsReleased) { @@ -126,9 +126,14 @@ void ReportUseAfterFree(const DeviceSanitizerReport &Report, auto AllocInfoItOp = context.interceptor->findAllocInfoByAddress(Report.Addr); - auto &AllocInfo = (*AllocInfoItOp)->second; + if (!AllocInfoItOp) { + context.logger.always("Failed to find which chunck {} is allocated", + (void *)Report.Addr); + return; + } - if (!AllocInfoItOp || AllocInfo->Context != Context) { + auto &AllocInfo = (*AllocInfoItOp)->second; + if (AllocInfo->Context != Context) { context.logger.always("Failed to find which chunck {} is allocated", (void *)Report.Addr); } diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.hpp b/source/loader/layers/sanitizer/symbolizer_llvm.hpp index 32afb903e0..af9fc02763 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.hpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.hpp @@ -21,6 +21,7 @@ namespace ur_sanitizer_layer { class SymbolizerTool { public: + virtual ~SymbolizerTool() {} virtual bool SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { std::ignore = BI; std::ignore = SI; diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index 4c7609ba36..08fa0d22fa 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -305,8 +305,6 @@ __urdlllocal ur_result_t UR_APICALL urContextRelease( return result; } -// TODO: urDeviceRelease - /////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's Context table /// with current process' addresses From 535996e4172173e45eb259bd113f6b3837016355 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 5 Mar 2024 19:14:04 -0800 Subject: [PATCH 27/42] fix device global on gpu & support fgpa emulator --- .../layers/sanitizer/asan_interceptor.cpp | 47 +++++++++----- .../layers/sanitizer/asan_interceptor.hpp | 9 ++- .../loader/layers/sanitizer/asan_report.cpp | 10 ++- .../loader/layers/sanitizer/asan_report.hpp | 6 +- .../sanitizer/device_sanitizer_report.hpp | 3 + source/loader/layers/sanitizer/ur_sanddi.cpp | 63 ++++++++++++++++++- .../layers/sanitizer/ur_sanitizer_utils.cpp | 11 ++++ .../layers/sanitizer/ur_sanitizer_utils.hpp | 9 +-- 8 files changed, 127 insertions(+), 31 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index f6d02508f3..1e9ca71c65 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -100,7 +100,12 @@ SanitizerInterceptor::SanitizerInterceptor() { KV = Options->find("quarantine_size_mb"); if (KV != Options->end()) { auto Value = KV->second.front(); - cl_MaxQuarantineSizeMB = std::stoul(Value); + try { + cl_MaxQuarantineSizeMB = std::stoul(Value); + } catch (...) { + die("[ERROR]: \"cl_MaxQuarantineSizeMB\" should be an " + "integer"); + } } if (cl_MaxQuarantineSizeMB) { m_Quarantine = @@ -317,8 +322,10 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, } if (AH.ErrorType == DeviceSanitizerErrorType::USE_AFTER_FREE) { ReportUseAfterFree(AH, Kernel, GetContext(Queue)); + } else if (AH.ErrorType == DeviceSanitizerErrorType::OUT_OF_BOUNDS) { + ReportOutOfBoundsError(AH, Kernel); } else { - ReportGenericError(AH, Kernel); + ReportGenericError(AH); } } } @@ -547,26 +554,16 @@ SanitizerInterceptor::registerDeviceGlobals(ur_context_handle_t Context, auto ContextInfo = getContextInfo(Context); for (auto Device : Devices) { - ur_queue_handle_t Queue; - ur_result_t Result = context.urDdiTable.Queue.pfnCreate( - Context, Device, nullptr, &Queue); - if (Result != UR_RESULT_SUCCESS) { - context.logger.error("Failed to create command queue: {}", Result); - return Result; - } + ManagedQueue Queue(Context, Device); uint64_t NumOfDeviceGlobal; - Result = context.urDdiTable.Enqueue.pfnDeviceGlobalVariableRead( + auto Result = context.urDdiTable.Enqueue.pfnDeviceGlobalVariableRead( Queue, Program, kSPIR_AsanDeviceGlobalCount, true, sizeof(NumOfDeviceGlobal), 0, &NumOfDeviceGlobal, 0, nullptr, nullptr); - if (Result == UR_RESULT_ERROR_INVALID_ARGUMENT) { + if (Result != UR_RESULT_SUCCESS) { context.logger.info("No device globals"); continue; - } else if (Result != UR_RESULT_SUCCESS) { - context.logger.error("Device Global[{}] Read Failed: {}", - kSPIR_AsanDeviceGlobalCount, Result); - return Result; } std::vector GVInfos(NumOfDeviceGlobal); @@ -696,6 +693,9 @@ ur_result_t SanitizerInterceptor::prepareLaunch( break; } + // LaunchInfo needs context to release shadow memory + LaunchInfo.setContext(Context); + // Write shadow memory offset for local memory auto LocalMemorySize = GetLocalMemorySize(DeviceInfo->Handle); auto LocalShadowMemorySize = @@ -713,8 +713,9 @@ ur_result_t SanitizerInterceptor::prepareLaunch( if (Result != UR_RESULT_SUCCESS) { context.logger.error( "Failed to allocate shadow memory for local memory: {}", - numWorkgroup, Result); - context.logger.error("Maybe the number of workgroup too large"); + Result); + context.logger.error("Maybe the number of workgroup ({}) too large", + numWorkgroup); return Result; } LaunchInfo.LocalShadowOffsetEnd = @@ -757,12 +758,24 @@ SanitizerInterceptor::findAllocInfoByAddress(uptr Address) { return --It; } +void LaunchInfo::setContext(ur_context_handle_t Context) { + [[maybe_unused]] auto Result = + context.urDdiTable.Context.pfnRetain(Context); + assert(Result == UR_RESULT_SUCCESS); + this->Context = Context; +} + LaunchInfo::~LaunchInfo() { if (LocalShadowOffset) { [[maybe_unused]] auto Result = context.urDdiTable.USM.pfnFree(Context, (void *)LocalShadowOffset); assert(Result == UR_RESULT_SUCCESS); } + if (Context) { + [[maybe_unused]] auto Result = + context.urDdiTable.Context.pfnRelease(Context); + assert(Result == UR_RESULT_SUCCESS); + } } } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 14cbbceec2..0869607f21 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -116,16 +116,15 @@ struct ContextInfo { }; struct LaunchInfo { - uptr LocalShadowOffset; - uptr LocalShadowOffsetEnd; - ur_context_handle_t Context; + uptr LocalShadowOffset = 0; + uptr LocalShadowOffsetEnd = 0; + ur_context_handle_t Context = nullptr; DeviceSanitizerReport SPIR_DeviceSanitizerReportMem; size_t LocalWorkSize[3]; - LaunchInfo() - : LocalShadowOffset(0), LocalShadowOffsetEnd(0), Context(nullptr) {} + void setContext(ur_context_handle_t Context); ~LaunchInfo(); }; diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index 5391d3ad16..e4ebdda103 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -80,8 +80,14 @@ void ReportDoubleFree(uptr Addr, const StackTrace &Stack, exit(1); } -void ReportGenericError(const DeviceSanitizerReport &Report, - ur_kernel_handle_t Kernel) { +void ReportGenericError(const DeviceSanitizerReport &Report) { + context.logger.always("\n====ERROR: DeviceSanitizer: {}", + ToString(Report.ErrorType)); + exit(1); +} + +void ReportOutOfBoundsError(const DeviceSanitizerReport &Report, + ur_kernel_handle_t Kernel) { const char *File = Report.File[0] ? Report.File : ""; const char *Func = Report.Func[0] ? Report.Func : ""; auto KernelName = GetKernelName(Kernel); diff --git a/source/loader/layers/sanitizer/asan_report.hpp b/source/loader/layers/sanitizer/asan_report.hpp index e1ac7daacf..d107b271c0 100644 --- a/source/loader/layers/sanitizer/asan_report.hpp +++ b/source/loader/layers/sanitizer/asan_report.hpp @@ -31,8 +31,10 @@ void ReportBadContext(uptr Addr, const StackTrace &stack, void ReportDoubleFree(uptr Addr, const StackTrace &Stack, const std::shared_ptr &AllocInfo); -void ReportGenericError(const DeviceSanitizerReport &Report, - ur_kernel_handle_t Kernel); +void ReportGenericError(const DeviceSanitizerReport &Report); + +void ReportOutOfBoundsError(const DeviceSanitizerReport &Report, + ur_kernel_handle_t Kernel); void ReportUseAfterFree(const DeviceSanitizerReport &Report, ur_kernel_handle_t Kernel, ur_context_handle_t Context); diff --git a/source/loader/layers/sanitizer/device_sanitizer_report.hpp b/source/loader/layers/sanitizer/device_sanitizer_report.hpp index b81554ef92..b5a52317b4 100644 --- a/source/loader/layers/sanitizer/device_sanitizer_report.hpp +++ b/source/loader/layers/sanitizer/device_sanitizer_report.hpp @@ -22,6 +22,7 @@ enum class DeviceSanitizerErrorType : int32_t { MISALIGNED, USE_AFTER_FREE, OUT_OF_SHADOW_BOUNDS, + UNKNOWN_DEVICE, }; enum class DeviceSanitizerMemoryType : int32_t { @@ -91,6 +92,8 @@ inline const char *ToString(DeviceSanitizerErrorType ErrorType) { return "use-after-free"; case DeviceSanitizerErrorType::OUT_OF_SHADOW_BOUNDS: return "out-of-shadow-bounds-access"; + case DeviceSanitizerErrorType::UNKNOWN_DEVICE: + return "unknown-device"; default: return "unknown-error"; } diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index 08fa0d22fa..f9349f26a8 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -13,6 +13,7 @@ #include "asan_interceptor.hpp" #include "symbolizer_llvm.hpp" #include "ur_sanitizer_layer.hpp" +#include "ur_sanitizer_utils.hpp" namespace ur_sanitizer_layer { @@ -150,6 +151,31 @@ __urdlllocal ur_result_t UR_APICALL urProgramBuild( return UR_RESULT_SUCCESS; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urProgramBuildExp +__urdlllocal ur_result_t UR_APICALL urProgramBuildExp( + ur_program_handle_t hProgram, ///< [in] Handle of the program to build. + uint32_t numDevices, ///< [in] number of devices + ur_device_handle_t * + phDevices, ///< [in][range(0, numDevices)] pointer to array of device handles + const char * + pOptions ///< [in][optional] pointer to build options null-terminated string. +) { + auto pfnBuildExp = context.urDdiTable.ProgramExp.pfnBuildExp; + + if (nullptr == pfnBuildExp) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + context.logger.debug("==== urProgramBuildExp"); + + UR_CALL(pfnBuildExp(hProgram, numDevices, phDevices, pOptions)); + UR_CALL(context.interceptor->registerDeviceGlobals(GetContext(hProgram), + hProgram)); + + return UR_RESULT_SUCCESS; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urEnqueueKernelLaunch __urdlllocal ur_result_t UR_APICALL urEnqueueKernelLaunch( @@ -189,7 +215,7 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueKernelLaunch( context.logger.debug("==== urEnqueueKernelLaunch"); - LaunchInfo LaunchInfo; + LaunchInfo LaunchInfo{}; const size_t *pUserLocalWorkSize = pLocalWorkSize; if (!pUserLocalWorkSize) { pUserLocalWorkSize = LaunchInfo.LocalWorkSize; @@ -368,6 +394,36 @@ __urdlllocal ur_result_t UR_APICALL urGetProgramProcAddrTable( return UR_RESULT_SUCCESS; } /////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's ProgramExp table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +__urdlllocal ur_result_t UR_APICALL urGetProgramExpProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_program_exp_dditable_t + *pDdiTable ///< [in,out] pointer to table of DDI function pointers +) { + if (nullptr == pDdiTable) { + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + } + + if (UR_MAJOR_VERSION(ur_sanitizer_layer::context.version) != + UR_MAJOR_VERSION(version) || + UR_MINOR_VERSION(ur_sanitizer_layer::context.version) > + UR_MINOR_VERSION(version)) { + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + } + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnBuildExp = ur_sanitizer_layer::urProgramBuildExp; + + return result; +} +/////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's Enqueue table /// with current process' addresses /// @@ -472,6 +528,11 @@ ur_result_t context_t::init(ur_dditable_t *dditable, UR_API_VERSION_CURRENT, &dditable->Program); } + if (UR_RESULT_SUCCESS == result) { + result = ur_sanitizer_layer::urGetProgramExpProcAddrTable( + UR_API_VERSION_CURRENT, &dditable->ProgramExp); + } + if (UR_RESULT_SUCCESS == result) { result = ur_sanitizer_layer::urGetEnqueueProcAddrTable( UR_API_VERSION_CURRENT, &dditable->Enqueue); diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp index 67d5b6ee88..7511679091 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp @@ -24,6 +24,15 @@ ur_context_handle_t GetContext(ur_queue_handle_t Queue) { return Context; } +ur_context_handle_t GetContext(ur_program_handle_t Program) { + ur_context_handle_t Context{}; + [[maybe_unused]] auto Result = context.urDdiTable.Program.pfnGetInfo( + Program, UR_PROGRAM_INFO_CONTEXT, sizeof(ur_context_handle_t), &Context, + nullptr); + assert(Result == UR_RESULT_SUCCESS && "getContext() failed"); + return Context; +} + ur_device_handle_t GetDevice(ur_queue_handle_t Queue) { ur_device_handle_t Device{}; [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( @@ -83,6 +92,8 @@ DeviceType GetDeviceType(ur_device_handle_t Device) { assert(Result == UR_RESULT_SUCCESS && "getDeviceType() failed"); switch (DeviceType) { case UR_DEVICE_TYPE_CPU: + case UR_DEVICE_TYPE_FPGA: + // TODO: Check fpga is fpga emulator return DeviceType::CPU; case UR_DEVICE_TYPE_GPU: { // TODO: Check device name diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp index 852d59314a..fbe74a78ed 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp @@ -17,13 +17,14 @@ namespace ur_sanitizer_layer { ur_context_handle_t GetContext(ur_queue_handle_t Queue); +ur_context_handle_t GetContext(ur_program_handle_t Program); ur_device_handle_t GetDevice(ur_queue_handle_t Queue); -ur_program_handle_t GetProgram(ur_kernel_handle_t Kernel); -size_t GetLocalMemorySize(ur_device_handle_t Device); +DeviceType GetDeviceType(ur_device_handle_t Device); std::string GetKernelName(ur_kernel_handle_t Kernel); +size_t GetLocalMemorySize(ur_device_handle_t Device); +ur_program_handle_t GetProgram(ur_kernel_handle_t Kernel); +std::vector GetProgramDevices(ur_program_handle_t Program); ur_device_handle_t GetUSMAllocDevice(ur_context_handle_t Context, const void *MemPtr); -DeviceType GetDeviceType(ur_device_handle_t Device); -std::vector GetProgramDevices(ur_program_handle_t Program); } // namespace ur_sanitizer_layer From 84644c13aea6774a832ffba80cf146f0c12abdd8 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 5 Mar 2024 23:28:59 -0800 Subject: [PATCH 28/42] fix LaunchInfo --- .../loader/layers/sanitizer/asan_interceptor.cpp | 14 ++++---------- .../loader/layers/sanitizer/asan_interceptor.hpp | 7 +++---- source/loader/layers/sanitizer/ur_sanddi.cpp | 2 +- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 1e9ca71c65..a87e10a7d5 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -693,9 +693,6 @@ ur_result_t SanitizerInterceptor::prepareLaunch( break; } - // LaunchInfo needs context to release shadow memory - LaunchInfo.setContext(Context); - // Write shadow memory offset for local memory auto LocalMemorySize = GetLocalMemorySize(DeviceInfo->Handle); auto LocalShadowMemorySize = @@ -758,11 +755,10 @@ SanitizerInterceptor::findAllocInfoByAddress(uptr Address) { return --It; } -void LaunchInfo::setContext(ur_context_handle_t Context) { +LaunchInfo::LaunchInfo(ur_context_handle_t Context) : Context(Context) { [[maybe_unused]] auto Result = context.urDdiTable.Context.pfnRetain(Context); assert(Result == UR_RESULT_SUCCESS); - this->Context = Context; } LaunchInfo::~LaunchInfo() { @@ -771,11 +767,9 @@ LaunchInfo::~LaunchInfo() { context.urDdiTable.USM.pfnFree(Context, (void *)LocalShadowOffset); assert(Result == UR_RESULT_SUCCESS); } - if (Context) { - [[maybe_unused]] auto Result = - context.urDdiTable.Context.pfnRelease(Context); - assert(Result == UR_RESULT_SUCCESS); - } + [[maybe_unused]] auto Result = + context.urDdiTable.Context.pfnRelease(Context); + assert(Result == UR_RESULT_SUCCESS); } } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 0869607f21..2b79349770 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -118,13 +118,12 @@ struct ContextInfo { struct LaunchInfo { uptr LocalShadowOffset = 0; uptr LocalShadowOffsetEnd = 0; - ur_context_handle_t Context = nullptr; - DeviceSanitizerReport SPIR_DeviceSanitizerReportMem; - size_t LocalWorkSize[3]; + ur_context_handle_t Context = nullptr; + size_t LocalWorkSize[3] = {0}; - void setContext(ur_context_handle_t Context); + explicit LaunchInfo(ur_context_handle_t Context); ~LaunchInfo(); }; diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index f9349f26a8..1ac09c18f8 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -215,7 +215,7 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueKernelLaunch( context.logger.debug("==== urEnqueueKernelLaunch"); - LaunchInfo LaunchInfo{}; + LaunchInfo LaunchInfo(GetContext(hQueue)); const size_t *pUserLocalWorkSize = pLocalWorkSize; if (!pUserLocalWorkSize) { pUserLocalWorkSize = LaunchInfo.LocalWorkSize; From f889e006eba189544707ba3917793cd955011d99 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 6 Mar 2024 21:39:53 -0800 Subject: [PATCH 29/42] clean code --- .../layers/sanitizer/asan_allocator.cpp | 2 +- .../layers/sanitizer/asan_allocator.hpp | 5 +++-- .../layers/sanitizer/asan_interceptor.cpp | 10 +++++----- .../layers/sanitizer/asan_interceptor.hpp | 9 --------- .../layers/sanitizer/asan_quarantine.hpp | 8 ++++---- .../loader/layers/sanitizer/asan_report.cpp | 20 +++++++++---------- .../layers/sanitizer/linux/backtrace.cpp | 1 - source/loader/layers/sanitizer/stacktrace.hpp | 2 +- .../layers/sanitizer/symbolizer_llvm.cpp | 2 +- .../layers/sanitizer/symbolizer_llvm.hpp | 4 ++-- 10 files changed, 27 insertions(+), 36 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_allocator.cpp b/source/loader/layers/sanitizer/asan_allocator.cpp index de332a40ec..0ac2fe6027 100644 --- a/source/loader/layers/sanitizer/asan_allocator.cpp +++ b/source/loader/layers/sanitizer/asan_allocator.cpp @@ -15,7 +15,7 @@ namespace ur_sanitizer_layer { -void AllocInfo::Print() { +void AllocInfo::print() { context.logger.info( "AllocInfo(AllocBegin={}, User={}-{}, AllocSize={}, Type={})", (void *)AllocBegin, (void *)UserBegin, (void *)UserEnd, AllocSize, diff --git a/source/loader/layers/sanitizer/asan_allocator.hpp b/source/loader/layers/sanitizer/asan_allocator.hpp index c2ba9819d0..88dfd2d074 100644 --- a/source/loader/layers/sanitizer/asan_allocator.hpp +++ b/source/loader/layers/sanitizer/asan_allocator.hpp @@ -21,6 +21,7 @@ namespace ur_sanitizer_layer { enum class AllocType : uint32_t { + UNKNOWN, DEVICE_USM, SHARED_USM, HOST_USM, @@ -34,7 +35,7 @@ struct AllocInfo { uptr UserEnd = 0; size_t AllocSize = 0; - AllocType Type = AllocType::DEVICE_USM; + AllocType Type = AllocType::UNKNOWN; bool IsReleased = false; ur_context_handle_t Context = nullptr; @@ -43,7 +44,7 @@ struct AllocInfo { StackTrace AllocStack; StackTrace ReleaseStack; - void Print(); + void print(); }; using AllocationMap = std::map>; diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index a87e10a7d5..5173a7271c 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -31,10 +31,10 @@ constexpr int kUsmSharedRedzoneMagic = (char)0x83; constexpr int kMemBufferRedzoneMagic = (char)0x84; constexpr int kDeviceGlobalRedZoneMagic = (char)0x85; -const int kUsmDeviceDeallocatedMagic = (char)0x91; -const int kUsmHostDeallocatedMagic = (char)0x92; -const int kUsmSharedDeallocatedMagic = (char)0x93; -const int kMemBufferDeallocatedMagic = (char)0x93; +constexpr int kUsmDeviceDeallocatedMagic = (char)0x91; +constexpr int kUsmHostDeallocatedMagic = (char)0x92; +constexpr int kUsmSharedDeallocatedMagic = (char)0x93; +constexpr int kMemBufferDeallocatedMagic = (char)0x93; constexpr auto kSPIR_AsanShadowMemoryGlobalStart = "__AsanShadowMemoryGlobalStart"; @@ -186,7 +186,7 @@ ur_result_t SanitizerInterceptor::allocateMemory( GetCurrentBacktrace(), {}}); - AI->Print(); + AI->print(); // For updating shadow memory if (Device) { // Device/Shared USM diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 2b79349770..2c4c971ee6 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -76,15 +76,6 @@ struct QueueInfo { context.urDdiTable.Queue.pfnRelease(Handle); assert(Result == UR_RESULT_SUCCESS); } - - static std::unique_ptr Create(ur_context_handle_t Context, - ur_device_handle_t Device) { - ur_queue_handle_t Queue{}; - [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnCreate( - Context, Device, nullptr, &Queue); - assert(Result == UR_RESULT_SUCCESS); - return std::make_unique(Queue); - } }; struct ContextInfo { diff --git a/source/loader/layers/sanitizer/asan_quarantine.hpp b/source/loader/layers/sanitizer/asan_quarantine.hpp index fb2d293082..3f07c62344 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.hpp +++ b/source/loader/layers/sanitizer/asan_quarantine.hpp @@ -29,14 +29,14 @@ class QuarantineCache { explicit QuarantineCache() {} // Total memory used, including internal accounting. - uptr Size() const { return m_Size; } + uptr size() const { return m_Size; } - void Enqueue(Element &It) { + void enqueue(Element &It) { m_List.push(It); m_Size += It->second->AllocSize; } - std::optional Dequeue() { + std::optional dequeue() { if (m_List.empty()) { return std::optional{}; } @@ -46,7 +46,7 @@ class QuarantineCache { return It; } - void PrintStats() const {} + void printStats() const {} private: List m_List; diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index e4ebdda103..4ba73253dc 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -23,7 +23,7 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, const std::shared_ptr &AI) { context.logger.always( "\n====ERROR: DeviceSanitizer: bad-free on address {}", (void *)Addr); - stack.Print(); + stack.print(); if (!AI) { context.logger.always("{} may be allocated on Host Memory", @@ -37,7 +37,7 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, (void *)Addr, ToString(AI->Type), (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); context.logger.always("allocated here:"); - AI->AllocStack.Print(); + AI->AllocStack.print(); exit(1); } @@ -47,17 +47,17 @@ void ReportBadContext(uptr Addr, const StackTrace &stack, context.logger.always( "\n====ERROR: DeviceSanitizer: bad-context on address {}", (void *)Addr); - stack.Print(); + stack.print(); context.logger.always("{} is located inside of {} region [{}, {})", (void *)Addr, ToString(AI->Type), (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); context.logger.always("allocated here:"); - AI->AllocStack.Print(); + AI->AllocStack.print(); if (AI->IsReleased) { context.logger.always("freed here:"); - AI->ReleaseStack.Print(); + AI->ReleaseStack.print(); } exit(1); @@ -68,15 +68,15 @@ void ReportDoubleFree(uptr Addr, const StackTrace &Stack, context.logger.always( "\n====ERROR: DeviceSanitizer: double-free on address {}", (void *)Addr); - Stack.Print(); + Stack.print(); context.logger.always("{} is located inside of {} region [{}, {})", (void *)Addr, ToString(AI->Type), (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); context.logger.always("freed here:"); - AI->ReleaseStack.Print(); + AI->ReleaseStack.print(); context.logger.always("previously allocated here:"); - AI->AllocStack.Print(); + AI->AllocStack.print(); exit(1); } @@ -150,9 +150,9 @@ void ReportUseAfterFree(const DeviceSanitizerReport &Report, (void *)AllocInfo->UserBegin, (void *)(AllocInfo->UserEnd + 1)); context.logger.always("allocated here:"); - AllocInfo->AllocStack.Print(); + AllocInfo->AllocStack.print(); context.logger.always("released here:"); - AllocInfo->ReleaseStack.Print(); + AllocInfo->ReleaseStack.print(); exit(1); } diff --git a/source/loader/layers/sanitizer/linux/backtrace.cpp b/source/loader/layers/sanitizer/linux/backtrace.cpp index 3a50c09655..2f4e9da120 100644 --- a/source/loader/layers/sanitizer/linux/backtrace.cpp +++ b/source/loader/layers/sanitizer/linux/backtrace.cpp @@ -9,7 +9,6 @@ */ #include "stacktrace.hpp" -#include #include #include diff --git a/source/loader/layers/sanitizer/stacktrace.hpp b/source/loader/layers/sanitizer/stacktrace.hpp index 4af6328560..31b661cc7d 100644 --- a/source/loader/layers/sanitizer/stacktrace.hpp +++ b/source/loader/layers/sanitizer/stacktrace.hpp @@ -23,7 +23,7 @@ constexpr size_t MAX_BACKTRACE_FRAMES = 64; struct StackTrace { std::vector stack; - void Print() const; + void print() const; }; StackTrace GetCurrentBacktrace(); diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.cpp b/source/loader/layers/sanitizer/symbolizer_llvm.cpp index 260fe17318..f936bd2ea5 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.cpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.cpp @@ -43,7 +43,7 @@ bool ExtractSourceInfo(const std::string &output, SourceInfo &SI) { } // namespace -bool LLVMSymbolizer::SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { +bool LLVMSymbolizer::symbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { std::stringstream ss; ss << "llvm-symbolizer --obj=" << BI.module << " " << BI.offset; auto result = RunCommand(ss.str().c_str()); diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.hpp b/source/loader/layers/sanitizer/symbolizer_llvm.hpp index af9fc02763..1e0eb52240 100644 --- a/source/loader/layers/sanitizer/symbolizer_llvm.hpp +++ b/source/loader/layers/sanitizer/symbolizer_llvm.hpp @@ -22,7 +22,7 @@ namespace ur_sanitizer_layer { class SymbolizerTool { public: virtual ~SymbolizerTool() {} - virtual bool SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { + virtual bool symbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { std::ignore = BI; std::ignore = SI; return false; @@ -31,7 +31,7 @@ class SymbolizerTool { class LLVMSymbolizer final : public SymbolizerTool { public: - bool SymbolizePC(const BacktraceInfo &BI, SourceInfo &SI) override; + bool symbolizePC(const BacktraceInfo &BI, SourceInfo &SI) override; }; extern std::vector> SymbolizerTools; From 196ac4b777b0a14f1f58951cdafe1a38e21793f0 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 6 Mar 2024 22:24:46 -0800 Subject: [PATCH 30/42] fix build --- source/loader/layers/sanitizer/asan_quarantine.cpp | 6 +++--- source/loader/layers/sanitizer/stacktrace.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_quarantine.cpp b/source/loader/layers/sanitizer/asan_quarantine.cpp index b2d7d2d123..201d828fa3 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.cpp +++ b/source/loader/layers/sanitizer/asan_quarantine.cpp @@ -20,14 +20,14 @@ std::vector Quarantine::put(ur_device_handle_t Device, auto AllocSize = AI->AllocSize; auto &Cache = m_Map[Device]; std::vector DequeueList; - while (Cache.Size() + AllocSize > m_MaxQuarantineSize) { - auto ElementOp = Cache.Dequeue(); + while (Cache.size() + AllocSize > m_MaxQuarantineSize) { + auto ElementOp = Cache.dequeue(); if (!ElementOp) { break; } DequeueList.emplace_back(*ElementOp); } - Cache.Enqueue(It); + Cache.enqueue(It); return DequeueList; } diff --git a/source/loader/layers/sanitizer/stacktrace.cpp b/source/loader/layers/sanitizer/stacktrace.cpp index b1ad371839..9f80b57829 100644 --- a/source/loader/layers/sanitizer/stacktrace.cpp +++ b/source/loader/layers/sanitizer/stacktrace.cpp @@ -29,7 +29,7 @@ bool StartWith(const std::string &Str, const char *Pattern) { } // namespace -void StackTrace::Print() const { +void StackTrace::print() const { if (!stack.size()) { context.logger.always(" failed to acquire backtrace"); } @@ -46,7 +46,7 @@ void StackTrace::Print() const { SourceInfo SI; for (auto &symbolizer : SymbolizerTools) { - if (symbolizer->SymbolizePC(BI, SI)) { + if (symbolizer->symbolizePC(BI, SI)) { break; } } From 4eefa5be4688c960735c12fc844e5f37ec6704e3 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Thu, 7 Mar 2024 18:33:35 -0800 Subject: [PATCH 31/42] fix large alignment --- .../layers/sanitizer/asan_interceptor.cpp | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 5173a7271c..dc63c3a65f 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -109,7 +109,7 @@ SanitizerInterceptor::SanitizerInterceptor() { } if (cl_MaxQuarantineSizeMB) { m_Quarantine = - std::make_unique(cl_MaxQuarantineSizeMB * 1024); + std::make_unique(cl_MaxQuarantineSizeMB * 1024 * 1024); } } @@ -129,23 +129,38 @@ ur_result_t SanitizerInterceptor::allocateMemory( ur_context_handle_t Context, ur_device_handle_t Device, const ur_usm_desc_t *Properties, ur_usm_pool_handle_t Pool, size_t Size, void **ResultPtr, AllocType Type) { - auto Alignment = Properties->align; - assert(Alignment == 0 || IsPowerOfTwo(Alignment)); + + if (Size == 0) { + *ResultPtr = nullptr; + return UR_RESULT_SUCCESS; + } auto ContextInfo = getContextInfo(Context); std::shared_ptr DeviceInfo = Device ? getDeviceInfo(Device) : nullptr; + /// Modified from llvm/compiler-rt/lib/asan/asan_allocator.cpp + uint32_t Alignment = Properties ? Properties->align : 0; + // Alignment must be zero or a power-of-two + if (0 != (Alignment & (Alignment - 1))) { + return UR_RESULT_ERROR_INVALID_ARGUMENT; + } + + const uint32_t MinAlignment = ASAN_SHADOW_GRANULARITY; if (Alignment == 0) { - Alignment = - DeviceInfo ? DeviceInfo->Alignment : ASAN_SHADOW_GRANULARITY; + Alignment = DeviceInfo ? DeviceInfo->Alignment : MinAlignment; + } + if (Alignment < MinAlignment) { + Alignment = MinAlignment; } - // Copy from LLVM compiler-rt/lib/asan uptr RZLog = ComputeRZLog(Size); uptr RZSize = RZLog2Size(RZLog); uptr RoundedSize = RoundUpTo(Size, Alignment); uptr NeededSize = RoundedSize + RZSize * 2; + if (Alignment > MinAlignment) { + NeededSize += Alignment; + } void *Allocated = nullptr; @@ -163,7 +178,6 @@ ur_result_t SanitizerInterceptor::allocateMemory( return UR_RESULT_ERROR_INVALID_ARGUMENT; } - // Copy from LLVM compiler-rt/lib/asan uptr AllocBegin = reinterpret_cast(Allocated); [[maybe_unused]] uptr AllocEnd = AllocBegin + NeededSize; uptr UserBegin = AllocBegin + RZSize; From 60f33bd6514ebc10b47210b74234cd628d083e55 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Mon, 11 Mar 2024 22:44:08 -0700 Subject: [PATCH 32/42] disable copy and skip size=0 --- source/loader/layers/sanitizer/asan_interceptor.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index dc63c3a65f..894927a3e5 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -64,6 +64,10 @@ struct ManagedQueue { assert(Result == UR_RESULT_SUCCESS); } + // Disable copy semantics + ManagedQueue(const ManagedQueue &) = delete; + ManagedQueue &operator=(const ManagedQueue &) = delete; + operator ur_queue_handle_t() { return Handle; } private: @@ -130,11 +134,6 @@ ur_result_t SanitizerInterceptor::allocateMemory( const ur_usm_desc_t *Properties, ur_usm_pool_handle_t Pool, size_t Size, void **ResultPtr, AllocType Type) { - if (Size == 0) { - *ResultPtr = nullptr; - return UR_RESULT_SUCCESS; - } - auto ContextInfo = getContextInfo(Context); std::shared_ptr DeviceInfo = Device ? getDeviceInfo(Device) : nullptr; From 726435d36a4e7e94b647ce93cc60112f128d44f1 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 12 Mar 2024 20:05:19 -0700 Subject: [PATCH 33/42] clean code --- source/loader/layers/sanitizer/asan_interceptor.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 2c4c971ee6..812f06b2da 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -154,11 +154,6 @@ class SanitizerInterceptor { std::shared_ptr &CI); ur_result_t eraseDevice(ur_device_handle_t Device); - ur_result_t insertQueue(ur_context_handle_t Context, - ur_queue_handle_t Queue); - ur_result_t eraseQueue(ur_context_handle_t Context, - ur_queue_handle_t Queue); - std::optional findAllocInfoByAddress(uptr Address); private: From e198d84bc27bbff0795d6f4ebe92c1aa961cf0e0 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 12 Mar 2024 23:09:47 -0700 Subject: [PATCH 34/42] move ManagedQueue --- .../layers/sanitizer/asan_interceptor.cpp | 23 ------------------- .../layers/sanitizer/ur_sanitizer_utils.cpp | 12 ++++++++++ .../layers/sanitizer/ur_sanitizer_utils.hpp | 14 +++++++++++ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 894927a3e5..e5657ca012 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -51,29 +51,6 @@ constexpr auto kSPIR_DeviceSanitizerReportMem = "__DeviceSanitizerReportMem"; constexpr auto kSPIR_AsanDeviceGlobalCount = "__AsanDeviceGlobalCount"; constexpr auto kSPIR_AsanDeviceGlobalMetadata = "__AsanDeviceGlobalMetadata"; -struct ManagedQueue { - ManagedQueue(ur_context_handle_t Context, ur_device_handle_t Device) { - [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnCreate( - Context, Device, nullptr, &Handle); - assert(Result == UR_RESULT_SUCCESS); - } - - ~ManagedQueue() { - [[maybe_unused]] auto Result = - context.urDdiTable.Queue.pfnRelease(Handle); - assert(Result == UR_RESULT_SUCCESS); - } - - // Disable copy semantics - ManagedQueue(const ManagedQueue &) = delete; - ManagedQueue &operator=(const ManagedQueue &) = delete; - - operator ur_queue_handle_t() { return Handle; } - - private: - ur_queue_handle_t Handle = nullptr; -}; - uptr MemToShadow_CPU(uptr USM_SHADOW_BASE, uptr UPtr) { return USM_SHADOW_BASE + (UPtr >> 3); } diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp index 7511679091..a18dc9f89d 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp @@ -15,6 +15,18 @@ namespace ur_sanitizer_layer { +ManagedQueue::ManagedQueue(ur_context_handle_t Context, + ur_device_handle_t Device) { + [[maybe_unused]] auto Result = + context.urDdiTable.Queue.pfnCreate(Context, Device, nullptr, &Handle); + assert(Result == UR_RESULT_SUCCESS); +} + +ManagedQueue::~ManagedQueue() { + [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnRelease(Handle); + assert(Result == UR_RESULT_SUCCESS); +} + ur_context_handle_t GetContext(ur_queue_handle_t Queue) { ur_context_handle_t Context{}; [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp index fbe74a78ed..47d9d4bf3b 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp @@ -16,6 +16,20 @@ namespace ur_sanitizer_layer { +struct ManagedQueue { + ManagedQueue(ur_context_handle_t Context, ur_device_handle_t Device); + ~ManagedQueue(); + + // Disable copy semantics + ManagedQueue(const ManagedQueue &) = delete; + ManagedQueue &operator=(const ManagedQueue &) = delete; + + operator ur_queue_handle_t() { return Handle; } + + private: + ur_queue_handle_t Handle = nullptr; +}; + ur_context_handle_t GetContext(ur_queue_handle_t Queue); ur_context_handle_t GetContext(ur_program_handle_t Program); ur_device_handle_t GetDevice(ur_queue_handle_t Queue); From 8c823c5959a106f0d7f7cac54aeb442e28117846 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sat, 23 Mar 2024 06:47:23 -0700 Subject: [PATCH 35/42] remove llvm-symbolizer --- source/loader/CMakeLists.txt | 2 - source/loader/layers/sanitizer/common.hpp | 6 +- .../layers/sanitizer/linux/backtrace.cpp | 37 +++-------- source/loader/layers/sanitizer/stacktrace.cpp | 35 ++-------- .../layers/sanitizer/symbolizer_llvm.cpp | 66 ------------------- .../layers/sanitizer/symbolizer_llvm.hpp | 40 ----------- source/loader/layers/sanitizer/ur_sanddi.cpp | 3 - 7 files changed, 18 insertions(+), 171 deletions(-) delete mode 100644 source/loader/layers/sanitizer/symbolizer_llvm.cpp delete mode 100644 source/loader/layers/sanitizer/symbolizer_llvm.hpp diff --git a/source/loader/CMakeLists.txt b/source/loader/CMakeLists.txt index d17764a6e2..78a9ed017a 100644 --- a/source/loader/CMakeLists.txt +++ b/source/loader/CMakeLists.txt @@ -120,8 +120,6 @@ if(UR_ENABLE_SANITIZER) ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/device_sanitizer_report.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/stacktrace.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/stacktrace.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/symbolizer_llvm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/symbolizer_llvm.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanddi.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanitizer_layer.hpp diff --git a/source/loader/layers/sanitizer/common.hpp b/source/loader/layers/sanitizer/common.hpp index dab6b61957..ae32941850 100644 --- a/source/loader/layers/sanitizer/common.hpp +++ b/source/loader/layers/sanitizer/common.hpp @@ -82,11 +82,7 @@ inline constexpr uptr ComputeRZLog(uptr user_requested_size) { return Result; \ } -struct BacktraceInfo { - uptr offset; - std::string module; - std::string debug; -}; +using BacktraceInfo = std::string; struct SourceInfo { std::string file; diff --git a/source/loader/layers/sanitizer/linux/backtrace.cpp b/source/loader/layers/sanitizer/linux/backtrace.cpp index 2f4e9da120..87c822d036 100644 --- a/source/loader/layers/sanitizer/linux/backtrace.cpp +++ b/source/loader/layers/sanitizer/linux/backtrace.cpp @@ -14,40 +14,23 @@ namespace ur_sanitizer_layer { -namespace { - -bool ExtractSymbolInfo(const char *symbol, BacktraceInfo &info) { - info.debug = std::string(symbol); - - auto s1 = std::strrchr(symbol, '('); - info.module = std::string(symbol, s1 - symbol); - auto s2 = std::strrchr(symbol, '['); - info.offset = std::stoull(s2 + 1, nullptr, 16); - return true; -} - -} // namespace - StackTrace GetCurrentBacktrace() { - void *backtraceFrames[MAX_BACKTRACE_FRAMES]; - int frameCount = backtrace(backtraceFrames, MAX_BACKTRACE_FRAMES); - char **backtraceStr = backtrace_symbols(backtraceFrames, frameCount); + void *Frames[MAX_BACKTRACE_FRAMES]; + int FrameCount = backtrace(Frames, MAX_BACKTRACE_FRAMES); + char **Symbols = backtrace_symbols(Frames, FrameCount); - if (backtraceStr == nullptr) { + if (Symbols == nullptr) { return StackTrace(); } - StackTrace stack; - for (int i = 0; i < frameCount; i++) { - BacktraceInfo addr_info; - if (!ExtractSymbolInfo(backtraceStr[i], addr_info)) { - continue; - } - stack.stack.emplace_back(std::move(addr_info)); + StackTrace Stack; + for (int i = 0; i < FrameCount; i++) { + BacktraceInfo addr_info(Symbols[i]); + Stack.stack.emplace_back(std::move(addr_info)); } - free(backtraceStr); + free(Symbols); - return stack; + return Stack; } } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/stacktrace.cpp b/source/loader/layers/sanitizer/stacktrace.cpp index 9f80b57829..6994ce58ad 100644 --- a/source/loader/layers/sanitizer/stacktrace.cpp +++ b/source/loader/layers/sanitizer/stacktrace.cpp @@ -11,20 +11,14 @@ */ #include "stacktrace.hpp" -#include "symbolizer_llvm.hpp" #include "ur_sanitizer_layer.hpp" namespace ur_sanitizer_layer { namespace { -std::string GetFileName(const std::string &FilePath) { - auto p = FilePath.find_last_of('/'); - return FilePath.substr(p + 1); -} - -bool StartWith(const std::string &Str, const char *Pattern) { - return Str.rfind(Pattern, 0) == 0; +bool Contains(const std::string &s, const char *p) { + return s.find(p) != std::string::npos; } } // namespace @@ -37,28 +31,13 @@ void StackTrace::print() const { unsigned index = 0; for (auto &BI : stack) { - auto ModuleFile = GetFileName(BI.module); - if (StartWith(ModuleFile, "libsycl.so") || - StartWith(ModuleFile, "libpi_unified_runtime.so") || - StartWith(ModuleFile, "libur_loader.so")) { + // Skip runtime modules + if (Contains(BI, "libsycl.so") || + Contains(BI, "libpi_unified_runtime.so") || + Contains(BI, "libur_loader.so")) { continue; } - - SourceInfo SI; - for (auto &symbolizer : SymbolizerTools) { - if (symbolizer->symbolizePC(BI, SI)) { - break; - } - } - - if (!SI.file.empty()) { - context.logger.always(" #{} {} in {} {}:{}:{}", index, - (void *)BI.offset, SI.function, SI.file, - SI.line, SI.column); - } else { - context.logger.always(" #{} {} in {} {}", index, (void *)BI.offset, - SI.function, BI.module); - } + context.logger.always(" #{} {}", index, BI); ++index; } context.logger.always(""); diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.cpp b/source/loader/layers/sanitizer/symbolizer_llvm.cpp deleted file mode 100644 index f936bd2ea5..0000000000 --- a/source/loader/layers/sanitizer/symbolizer_llvm.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Copyright (C) 2024 Intel Corporation - * - * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. - * See LICENSE.TXT - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - * - * @file symbolizer_llvm.cpp - * - */ - -#include "symbolizer_llvm.hpp" -#include "ur_sanitizer_layer.hpp" - -#include -#include - -namespace ur_sanitizer_layer { - -std::vector> SymbolizerTools; - -namespace { - -bool ExtractSourceInfo(const std::string &output, SourceInfo &SI) { - auto p1 = output.find('\n'); - std::string function = output.substr(0, p1); - auto p2 = output.find(':', ++p1); - std::string file = output.substr(p1, p2 - p1); - auto p3 = output.find(':', ++p2); - int line = std::stoi(output.substr(p2, p3 - p2)); - int column = std::stoi(output.substr(++p3)); - if (function != "??") { - SI.function = std::move(function); - } - if (file != "??") { - SI.file = std::move(file); - } - SI.line = line; - SI.column = column; - return true; -} - -} // namespace - -bool LLVMSymbolizer::symbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { - std::stringstream ss; - ss << "llvm-symbolizer --obj=" << BI.module << " " << BI.offset; - auto result = RunCommand(ss.str().c_str()); - ExtractSourceInfo(result, SI); - return true; -} - -void InitSymbolizers() { - auto result = RunCommand("llvm-symbolizer -v"); - if (result.size()) { - SymbolizerTools.emplace_back(std::make_unique()); - } - - if (SymbolizerTools.empty()) { - context.logger.always("[WARNING]: llvm-symbolizer is needed " - "for UR_LAYER_ASAN"); - } -} - -} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/symbolizer_llvm.hpp b/source/loader/layers/sanitizer/symbolizer_llvm.hpp deleted file mode 100644 index 1e0eb52240..0000000000 --- a/source/loader/layers/sanitizer/symbolizer_llvm.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Copyright (C) 2024 Intel Corporation - * - * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. - * See LICENSE.TXT - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - * - * @file symbolizer_llvm.hpp - * - */ - -#pragma once - -#include "common.hpp" - -#include -#include - -namespace ur_sanitizer_layer { - -class SymbolizerTool { - public: - virtual ~SymbolizerTool() {} - virtual bool symbolizePC(const BacktraceInfo &BI, SourceInfo &SI) { - std::ignore = BI; - std::ignore = SI; - return false; - } -}; - -class LLVMSymbolizer final : public SymbolizerTool { - public: - bool symbolizePC(const BacktraceInfo &BI, SourceInfo &SI) override; -}; - -extern std::vector> SymbolizerTools; -void InitSymbolizers(); - -} // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index 1ac09c18f8..150eca3147 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -11,7 +11,6 @@ */ #include "asan_interceptor.hpp" -#include "symbolizer_llvm.hpp" #include "ur_sanitizer_layer.hpp" #include "ur_sanitizer_utils.hpp" @@ -543,8 +542,6 @@ ur_result_t context_t::init(ur_dditable_t *dditable, UR_API_VERSION_CURRENT, &dditable->USM); } - InitSymbolizers(); - return result; } From 77a042210ab3ac82797de8eaa935bb91f3ae7749 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Sun, 24 Mar 2024 02:05:01 -0700 Subject: [PATCH 36/42] sycn with latest code --- .../layers/sanitizer/asan_allocator.cpp | 6 +- .../layers/sanitizer/asan_interceptor.cpp | 236 +++++++++--------- .../layers/sanitizer/asan_interceptor.hpp | 46 ++-- ...anitizer_report.hpp => asan_libdevice.hpp} | 51 +++- .../layers/sanitizer/asan_quarantine.cpp | 4 +- .../layers/sanitizer/asan_quarantine.hpp | 9 +- .../loader/layers/sanitizer/asan_report.cpp | 21 +- source/loader/layers/sanitizer/common.hpp | 3 - source/loader/layers/sanitizer/ur_sanddi.cpp | 30 +-- .../layers/sanitizer/ur_sanitizer_utils.cpp | 39 ++- .../layers/sanitizer/ur_sanitizer_utils.hpp | 4 + 11 files changed, 270 insertions(+), 179 deletions(-) rename source/loader/layers/sanitizer/{device_sanitizer_report.hpp => asan_libdevice.hpp} (54%) diff --git a/source/loader/layers/sanitizer/asan_allocator.cpp b/source/loader/layers/sanitizer/asan_allocator.cpp index 0ac2fe6027..1ffa477ca1 100644 --- a/source/loader/layers/sanitizer/asan_allocator.cpp +++ b/source/loader/layers/sanitizer/asan_allocator.cpp @@ -17,9 +17,9 @@ namespace ur_sanitizer_layer { void AllocInfo::print() { context.logger.info( - "AllocInfo(AllocBegin={}, User={}-{}, AllocSize={}, Type={})", - (void *)AllocBegin, (void *)UserBegin, (void *)UserEnd, AllocSize, - ToString(Type)); + "AllocInfo(Alloc=[{}-{}), User=[{}-{}), AllocSize={}, Type={})", + (void *)AllocBegin, (void *)(AllocBegin + AllocSize), (void *)UserBegin, + (void *)(UserEnd), AllocSize, ToString(Type)); } } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index e5657ca012..c60b9c75b5 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -15,7 +15,6 @@ #include "asan_quarantine.hpp" #include "asan_report.hpp" #include "asan_shadow_setup.hpp" -#include "device_sanitizer_report.hpp" #include "stacktrace.hpp" #include "ur_sanitizer_utils.hpp" @@ -23,34 +22,8 @@ namespace ur_sanitizer_layer { namespace { -// These magic values are written to shadow for better error -// reporting. -constexpr int kUsmDeviceRedzoneMagic = (char)0x81; -constexpr int kUsmHostRedzoneMagic = (char)0x82; -constexpr int kUsmSharedRedzoneMagic = (char)0x83; -constexpr int kMemBufferRedzoneMagic = (char)0x84; -constexpr int kDeviceGlobalRedZoneMagic = (char)0x85; - -constexpr int kUsmDeviceDeallocatedMagic = (char)0x91; -constexpr int kUsmHostDeallocatedMagic = (char)0x92; -constexpr int kUsmSharedDeallocatedMagic = (char)0x93; -constexpr int kMemBufferDeallocatedMagic = (char)0x93; - -constexpr auto kSPIR_AsanShadowMemoryGlobalStart = - "__AsanShadowMemoryGlobalStart"; -constexpr auto kSPIR_AsanShadowMemoryGlobalEnd = "__AsanShadowMemoryGlobalEnd"; -constexpr auto kSPIR_AsanShadowMemoryLocalStart = - "__AsanShadowMemoryLocalStart"; -constexpr auto kSPIR_AsanShadowMemoryLocalEnd = "__AsanShadowMemoryLocalEnd"; - -constexpr auto kSPIR_DeviceType = "__DeviceType"; -constexpr auto kSPIR_AsanDebug = "__AsanDebug"; - constexpr auto kSPIR_DeviceSanitizerReportMem = "__DeviceSanitizerReportMem"; -constexpr auto kSPIR_AsanDeviceGlobalCount = "__AsanDeviceGlobalCount"; -constexpr auto kSPIR_AsanDeviceGlobalMetadata = "__AsanDeviceGlobalMetadata"; - uptr MemToShadow_CPU(uptr USM_SHADOW_BASE, uptr UPtr) { return USM_SHADOW_BASE + (UPtr >> 3); } @@ -64,6 +37,14 @@ uptr MemToShadow_PVC(uptr USM_SHADOW_BASE, uptr UPtr) { } } +ur_result_t urEnqueueUSMSet(ur_queue_handle_t Queue, void *Ptr, char Value, + size_t Size, uint32_t NumEvents = 0, + const ur_event_handle_t *EventWaitList = nullptr, + ur_event_handle_t *OutEvent = nullptr) { + return context.urDdiTable.Enqueue.pfnUSMFill( + Queue, Ptr, 1, &Value, Size, NumEvents, EventWaitList, OutEvent); +} + } // namespace SanitizerInterceptor::SanitizerInterceptor() { @@ -71,13 +52,13 @@ SanitizerInterceptor::SanitizerInterceptor() { if (!Options.has_value()) { return; } + auto KV = Options->find("debug"); if (KV != Options->end()) { auto Value = KV->second.front(); - if (Value == "1" || Value == "true") { - cl_Debug = 1; - } + cl_Debug = Value == "1" || Value == "true" ? 1 : 0; } + KV = Options->find("quarantine_size_mb"); if (KV != Options->end()) { auto Value = KV->second.front(); @@ -92,6 +73,12 @@ SanitizerInterceptor::SanitizerInterceptor() { m_Quarantine = std::make_unique(cl_MaxQuarantineSizeMB * 1024 * 1024); } + + KV = Options->find("detect_locals"); + if (KV != Options->end()) { + auto Value = KV->second.front(); + cl_DetectLocals = Value == "1" || Value == "true" ? 1 : 0; + } } SanitizerInterceptor::~SanitizerInterceptor() { @@ -109,7 +96,7 @@ SanitizerInterceptor::~SanitizerInterceptor() { ur_result_t SanitizerInterceptor::allocateMemory( ur_context_handle_t Context, ur_device_handle_t Device, const ur_usm_desc_t *Properties, ur_usm_pool_handle_t Pool, size_t Size, - void **ResultPtr, AllocType Type) { + AllocType Type, void **ResultPtr) { auto ContextInfo = getContextInfo(Context); std::shared_ptr DeviceInfo = @@ -265,8 +252,7 @@ ur_result_t SanitizerInterceptor::releaseMemory(ur_context_handle_t Context, ur_result_t SanitizerInterceptor::preLaunchKernel(ur_kernel_handle_t Kernel, ur_queue_handle_t Queue, - LaunchInfo &LaunchInfo, - uint32_t numWorkgroup) { + LaunchInfo &LaunchInfo) { auto Context = GetContext(Queue); auto Device = GetDevice(Queue); auto ContextInfo = getContextInfo(Context); @@ -278,20 +264,18 @@ ur_result_t SanitizerInterceptor::preLaunchKernel(ur_kernel_handle_t Kernel, return UR_RESULT_ERROR_INVALID_QUEUE; } - UR_CALL(prepareLaunch(Context, DeviceInfo, InternalQueue, Kernel, - LaunchInfo, numWorkgroup)); + UR_CALL( + prepareLaunch(Context, DeviceInfo, InternalQueue, Kernel, LaunchInfo)); UR_CALL(updateShadowMemory(ContextInfo, DeviceInfo, InternalQueue)); - UR_CALL(context.urDdiTable.Queue.pfnFinish(InternalQueue)); - return UR_RESULT_SUCCESS; } -void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, - ur_queue_handle_t Queue, - ur_event_handle_t &Event, - LaunchInfo &LaunchInfo) { +ur_result_t SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, + ur_queue_handle_t Queue, + ur_event_handle_t &Event, + LaunchInfo &LaunchInfo) { auto Program = GetProgram(Kernel); ur_event_handle_t ReadEvent{}; @@ -308,7 +292,7 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, const auto &AH = LaunchInfo.SPIR_DeviceSanitizerReportMem; if (!AH.Flag) { - return; + return UR_RESULT_SUCCESS; } if (AH.ErrorType == DeviceSanitizerErrorType::USE_AFTER_FREE) { ReportUseAfterFree(AH, Kernel, GetContext(Queue)); @@ -318,6 +302,8 @@ void SanitizerInterceptor::postLaunchKernel(ur_kernel_handle_t Kernel, ReportGenericError(AH); } } + + return Result; } ur_result_t DeviceInfo::allocShadowMemory(ur_context_handle_t Context) { @@ -352,27 +338,17 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( } MemSet((void *)ShadowBegin, Value, ShadowEnd - ShadowBegin + 1); - context.logger.debug( - "enqueueMemSetShadow (addr={}, count={}, value={})", - (void *)ShadowBegin, ShadowEnd - ShadowBegin + 1, - (void *)(size_t)Value); + context.logger.debug("enqueueMemSetShadow(addr={}, count={}, value={})", + (void *)ShadowBegin, ShadowEnd - ShadowBegin + 1, + (void *)(size_t)Value); } else if (DeviceInfo->Type == DeviceType::GPU_PVC) { uptr ShadowBegin = MemToShadow_PVC(DeviceInfo->ShadowOffset, Ptr); uptr ShadowEnd = MemToShadow_PVC(DeviceInfo->ShadowOffset, Ptr + Size - 1); { - static const size_t PageSize = [Context, &DeviceInfo]() { - size_t Size; - [[maybe_unused]] auto Result = - context.urDdiTable.VirtualMem.pfnGranularityGetInfo( - Context, DeviceInfo->Handle, - UR_VIRTUAL_MEM_GRANULARITY_INFO_RECOMMENDED, - sizeof(Size), &Size, nullptr); - assert(Result == UR_RESULT_SUCCESS); - context.logger.info("PVC PageSize: {}", Size); - return Size; - }(); + static const size_t PageSize = + GetVirtualMemGranularity(Context, DeviceInfo->Handle); ur_physical_mem_properties_t Desc{ UR_STRUCTURE_TYPE_PHYSICAL_MEM_PROPERTIES, nullptr, 0}; @@ -408,11 +384,8 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( // Reset PhysicalMem to null since it's been mapped PhysicalMem = nullptr; - const char Pattern[] = {0}; - - auto URes = context.urDdiTable.Enqueue.pfnUSMFill( - Queue, (void *)MappedPtr, 1, Pattern, PageSize, 0, - nullptr, nullptr); + auto URes = + urEnqueueUSMSet(Queue, (void *)MappedPtr, 0, PageSize); if (URes != UR_RESULT_SUCCESS) { context.logger.error("urEnqueueUSMFill(): {}", URes); return URes; @@ -421,10 +394,8 @@ ur_result_t SanitizerInterceptor::enqueueMemSetShadow( } } - const char Pattern[] = {(char)Value}; - auto URes = context.urDdiTable.Enqueue.pfnUSMFill( - Queue, (void *)ShadowBegin, 1, Pattern, ShadowEnd - ShadowBegin + 1, - 0, nullptr, nullptr); + auto URes = urEnqueueUSMSet(Queue, (void *)ShadowBegin, Value, + ShadowEnd - ShadowBegin + 1); context.logger.debug( "enqueueMemSetShadow (addr={}, count={}, value={}): {}", (void *)ShadowBegin, ShadowEnd - ShadowBegin + 1, @@ -504,7 +475,7 @@ ur_result_t SanitizerInterceptor::enqueueAllocInfo( ShadowByte = kMemBufferRedzoneMagic; break; case AllocType::DEVICE_GLOBAL: - ShadowByte = kDeviceGlobalRedZoneMagic; + ShadowByte = kDeviceGlobalRedzoneMagic; break; default: ShadowByte = 0xff; @@ -569,10 +540,17 @@ SanitizerInterceptor::registerDeviceGlobals(ur_context_handle_t Context, auto DeviceInfo = getDeviceInfo(Device); for (size_t i = 0; i < NumOfDeviceGlobal; i++) { - auto AI = std::make_shared(AllocInfo{ - GVInfos[i].Addr, GVInfos[i].Addr, - GVInfos[i].Addr + GVInfos[i].Size, GVInfos[i].SizeWithRedZone, - AllocType::DEVICE_GLOBAL}); + auto AI = std::make_shared( + AllocInfo{GVInfos[i].Addr, + GVInfos[i].Addr, + GVInfos[i].Addr + GVInfos[i].Size, + GVInfos[i].SizeWithRedZone, + AllocType::DEVICE_GLOBAL, + false, + Context, + Device, + GetCurrentBacktrace(), + {}}); ContextInfo->insertAllocInfo({Device}, AI); } @@ -644,12 +622,12 @@ ur_result_t SanitizerInterceptor::eraseDevice(ur_device_handle_t Device) { ur_result_t SanitizerInterceptor::prepareLaunch( ur_context_handle_t Context, std::shared_ptr &DeviceInfo, - ur_queue_handle_t Queue, ur_kernel_handle_t Kernel, LaunchInfo &LaunchInfo, - uint32_t numWorkgroup) { + ur_queue_handle_t Queue, ur_kernel_handle_t Kernel, + LaunchInfo &LaunchInfo) { auto Program = GetProgram(Kernel); do { - // Set global variable to program + // Write global variable to program auto EnqueueWriteGlobal = [Queue, Program](const char *Name, const void *Value, size_t Size) { auto Result = @@ -683,53 +661,71 @@ ur_result_t SanitizerInterceptor::prepareLaunch( break; } - // Write shadow memory offset for local memory - auto LocalMemorySize = GetLocalMemorySize(DeviceInfo->Handle); - auto LocalShadowMemorySize = - (numWorkgroup * LocalMemorySize) >> ASAN_SHADOW_SCALE; - - context.logger.info("LocalInfo(WorkGroup={}, LocalMemorySize={}, " - "LocalShadowMemorySize={})", - numWorkgroup, LocalMemorySize, - LocalShadowMemorySize); - - ur_usm_desc_t Desc{UR_STRUCTURE_TYPE_USM_HOST_DESC, nullptr, 0, 0}; - auto Result = context.urDdiTable.USM.pfnDeviceAlloc( - Context, DeviceInfo->Handle, &Desc, nullptr, LocalShadowMemorySize, - (void **)&LaunchInfo.LocalShadowOffset); - if (Result != UR_RESULT_SUCCESS) { - context.logger.error( - "Failed to allocate shadow memory for local memory: {}", - Result); - context.logger.error("Maybe the number of workgroup ({}) too large", - numWorkgroup); - return Result; + if (LaunchInfo.LocalWorkSize.empty()) { + LaunchInfo.LocalWorkSize.reserve(3); + // FIXME: This is W/A until urKernelSuggestGroupSize is added + LaunchInfo.LocalWorkSize[0] = 1; + LaunchInfo.LocalWorkSize[1] = 1; + LaunchInfo.LocalWorkSize[2] = 1; } - LaunchInfo.LocalShadowOffsetEnd = - LaunchInfo.LocalShadowOffset + LocalShadowMemorySize - 1; - - EnqueueWriteGlobal(kSPIR_AsanShadowMemoryLocalStart, - &LaunchInfo.LocalShadowOffset, - sizeof(LaunchInfo.LocalShadowOffset)); - EnqueueWriteGlobal(kSPIR_AsanShadowMemoryLocalEnd, - &LaunchInfo.LocalShadowOffsetEnd, - sizeof(LaunchInfo.LocalShadowOffsetEnd)); - { - const char Pattern[] = {0}; + const size_t *LocalWorkSize = LaunchInfo.LocalWorkSize.data(); + uint32_t NumWG = 1; + for (uint32_t Dim = 0; Dim < LaunchInfo.WorkDim; ++Dim) { + NumWG *= (LaunchInfo.GlobalWorkSize[Dim] + LocalWorkSize[Dim] - 1) / + LocalWorkSize[Dim]; + } - auto URes = context.urDdiTable.Enqueue.pfnUSMFill( - Queue, (void *)LaunchInfo.LocalShadowOffset, 1, Pattern, - LocalShadowMemorySize, 0, nullptr, nullptr); + auto EnqueueAllocateDevice = [Context, &DeviceInfo, Queue, + NumWG](size_t Size, uptr &Ptr) { + auto URes = context.urDdiTable.USM.pfnDeviceAlloc( + Context, DeviceInfo->Handle, nullptr, nullptr, Size, + (void **)&Ptr); if (URes != UR_RESULT_SUCCESS) { - context.logger.error("urEnqueueUSMFill(): {}", URes); + context.logger.error( + "Failed to allocate shadow memory for local memory: {}", + URes); + context.logger.error( + "Maybe the number of workgroup ({}) too large", NumWG); return URes; } - } + // Initialize shadow memory of local memory + URes = urEnqueueUSMSet(Queue, (void *)Ptr, 0, Size); + if (URes == UR_RESULT_ERROR_OUT_OF_DEVICE_MEMORY) { + context.logger.error( + "Failed to allocate shadow memory for local memory: {}", + URes); + context.logger.error( + "Maybe the number of workgroup ({}) too large", NumWG); + return URes; + } + return URes; + }; - context.logger.info("ShadowMemory(Local, {} - {})", - (void *)LaunchInfo.LocalShadowOffset, - (void *)LaunchInfo.LocalShadowOffsetEnd); + // Write shadow memory offset for local memory + if (cl_DetectLocals) { + // CPU needn't this + if (DeviceInfo->Type == DeviceType::GPU_PVC) { + size_t LocalMemorySize = GetLocalMemorySize(DeviceInfo->Handle); + size_t LocalShadowMemorySize = + (NumWG * LocalMemorySize) >> ASAN_SHADOW_SCALE; + + context.logger.debug( + "LocalMemoryInfo(WorkGroup={}, LocalMemorySize={}, " + "LocalShadowMemorySize={})", + NumWG, LocalMemorySize, LocalShadowMemorySize); + + UR_CALL(EnqueueAllocateDevice(LocalShadowMemorySize, + LaunchInfo.LocalShadowOffset)); + + LaunchInfo.LocalShadowOffsetEnd = + LaunchInfo.LocalShadowOffset + LocalShadowMemorySize - 1; + + context.logger.info("ShadowMemory(Local, {} - {})", + (void *)LaunchInfo.LocalShadowOffset, + (void *)LaunchInfo.LocalShadowOffsetEnd); + } + } } while (false); return UR_RESULT_SUCCESS; @@ -745,10 +741,20 @@ SanitizerInterceptor::findAllocInfoByAddress(uptr Address) { return --It; } -LaunchInfo::LaunchInfo(ur_context_handle_t Context) : Context(Context) { +LaunchInfo::LaunchInfo(ur_context_handle_t Context, + const size_t *GlobalWorkSize, + const size_t *LocalWorkSize, + const size_t *GlobalWorkOffset, uint32_t WorkDim) + : Context(Context), GlobalWorkSize(GlobalWorkSize), + GlobalWorkOffset(GlobalWorkOffset), WorkDim(WorkDim) { [[maybe_unused]] auto Result = context.urDdiTable.Context.pfnRetain(Context); assert(Result == UR_RESULT_SUCCESS); + + if (LocalWorkSize) { + this->LocalWorkSize = + std::vector(LocalWorkSize, LocalWorkSize + WorkDim); + } } LaunchInfo::~LaunchInfo() { diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 812f06b2da..6d2fd79188 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -13,8 +13,8 @@ #pragma once #include "asan_allocator.hpp" +#include "asan_libdevice.hpp" #include "common.hpp" -#include "device_sanitizer_report.hpp" #include "ur_sanitizer_layer.hpp" #include @@ -61,7 +61,8 @@ struct DeviceInfo { struct QueueInfo { ur_queue_handle_t Handle; - ur_mutex Mutex; + + ur_shared_mutex Mutex; ur_event_handle_t LastEvent; explicit QueueInfo(ur_queue_handle_t Queue) @@ -112,9 +113,14 @@ struct LaunchInfo { DeviceSanitizerReport SPIR_DeviceSanitizerReportMem; ur_context_handle_t Context = nullptr; - size_t LocalWorkSize[3] = {0}; - - explicit LaunchInfo(ur_context_handle_t Context); + const size_t *GlobalWorkSize = nullptr; + const size_t *GlobalWorkOffset = nullptr; + std::vector LocalWorkSize; + uint32_t WorkDim = 0; + + LaunchInfo(ur_context_handle_t Context, const size_t *GlobalWorkSize, + const size_t *LocalWorkSize, const size_t *GlobalWorkOffset, + uint32_t WorkDim); ~LaunchInfo(); }; @@ -134,17 +140,20 @@ class SanitizerInterceptor { ur_device_handle_t Device, const ur_usm_desc_t *Properties, ur_usm_pool_handle_t Pool, size_t Size, - void **ResultPtr, AllocType Type); + AllocType Type, void **ResultPtr); ur_result_t releaseMemory(ur_context_handle_t Context, void *Ptr); ur_result_t registerDeviceGlobals(ur_context_handle_t Context, ur_program_handle_t Program); ur_result_t preLaunchKernel(ur_kernel_handle_t Kernel, - ur_queue_handle_t Queue, LaunchInfo &LaunchInfo, - uint32_t numWorkgroup); - void postLaunchKernel(ur_kernel_handle_t Kernel, ur_queue_handle_t Queue, - ur_event_handle_t &Event, LaunchInfo &LaunchInfo); + ur_queue_handle_t Queue, + LaunchInfo &LaunchInfo); + + ur_result_t postLaunchKernel(ur_kernel_handle_t Kernel, + ur_queue_handle_t Queue, + ur_event_handle_t &Event, + LaunchInfo &LaunchInfo); ur_result_t insertContext(ur_context_handle_t Context, std::shared_ptr &CI); @@ -156,6 +165,12 @@ class SanitizerInterceptor { std::optional findAllocInfoByAddress(uptr Address); + std::shared_ptr getContextInfo(ur_context_handle_t Context) { + std::shared_lock Guard(m_ContextMapMutex); + assert(m_ContextMap.find(Context) != m_ContextMap.end()); + return m_ContextMap[Context]; + } + private: ur_result_t updateShadowMemory(std::shared_ptr &ContextInfo, std::shared_ptr &DeviceInfo, @@ -169,8 +184,8 @@ class SanitizerInterceptor { ur_result_t prepareLaunch(ur_context_handle_t Context, std::shared_ptr &DeviceInfo, ur_queue_handle_t Queue, - ur_kernel_handle_t Kernel, LaunchInfo &LaunchInfo, - uint32_t numWorkgroup); + ur_kernel_handle_t Kernel, + LaunchInfo &LaunchInfo); ur_result_t allocShadowMemory(ur_context_handle_t Context, std::shared_ptr &DeviceInfo); @@ -179,12 +194,6 @@ class SanitizerInterceptor { ur_queue_handle_t Queue, uptr Addr, uptr Size, u8 Value); - std::shared_ptr getContextInfo(ur_context_handle_t Context) { - std::shared_lock Guard(m_ContextMapMutex); - assert(m_ContextMap.find(Context) != m_ContextMap.end()); - return m_ContextMap[Context]; - } - std::shared_ptr getDeviceInfo(ur_device_handle_t Device) { std::shared_lock Guard(m_DeviceMapMutex); assert(m_DeviceMap.find(Device) != m_DeviceMap.end()); @@ -206,6 +215,7 @@ class SanitizerInterceptor { uint64_t cl_Debug = 0; uint32_t cl_MaxQuarantineSizeMB = 0; + bool cl_DetectLocals = true; std::unique_ptr m_Quarantine; }; diff --git a/source/loader/layers/sanitizer/device_sanitizer_report.hpp b/source/loader/layers/sanitizer/asan_libdevice.hpp similarity index 54% rename from source/loader/layers/sanitizer/device_sanitizer_report.hpp rename to source/loader/layers/sanitizer/asan_libdevice.hpp index b5a52317b4..ea2ffd8fe4 100644 --- a/source/loader/layers/sanitizer/device_sanitizer_report.hpp +++ b/source/loader/layers/sanitizer/asan_libdevice.hpp @@ -23,6 +23,7 @@ enum class DeviceSanitizerErrorType : int32_t { USE_AFTER_FREE, OUT_OF_SHADOW_BOUNDS, UNKNOWN_DEVICE, + NULL_POINTER, }; enum class DeviceSanitizerMemoryType : int32_t { @@ -39,8 +40,8 @@ enum class DeviceSanitizerMemoryType : int32_t { struct DeviceSanitizerReport { int Flag = 0; - char File[256 + 1] = ""; - char Func[256 + 1] = ""; + char File[256 + 1] = {}; + char Func[256 + 1] = {}; int32_t Line = 0; @@ -52,15 +53,53 @@ struct DeviceSanitizerReport { uint64_t LID1 = 0; uint64_t LID2 = 0; - uint64_t Addr = 0; + uintptr_t Address = 0; bool IsWrite = false; uint32_t AccessSize = 0; - DeviceSanitizerMemoryType MemoryType; - DeviceSanitizerErrorType ErrorType; + DeviceSanitizerMemoryType MemoryType = DeviceSanitizerMemoryType::UNKNOWN; + DeviceSanitizerErrorType ErrorType = DeviceSanitizerErrorType::UNKNOWN; bool IsRecover = false; }; +constexpr unsigned ASAN_SHADOW_SCALE = 3; +constexpr unsigned ASAN_SHADOW_GRANULARITY = 1ULL << ASAN_SHADOW_SCALE; + +// Based on the observation, only the last 24 bits of the address of the private +// variable have changed, we use 31 bits(2G) to be safe. +constexpr std::size_t ASAN_PRIVATE_SIZE = 0x7fffffffULL + 1; + +// These magic values are written to shadow for better error +// reporting. +constexpr int kUsmDeviceRedzoneMagic = (char)0x81; +constexpr int kUsmHostRedzoneMagic = (char)0x82; +constexpr int kUsmSharedRedzoneMagic = (char)0x83; +constexpr int kMemBufferRedzoneMagic = (char)0x84; +constexpr int kDeviceGlobalRedzoneMagic = (char)0x85; +constexpr int kNullPointerRedzoneMagic = (char)0x86; + +constexpr int kUsmDeviceDeallocatedMagic = (char)0x91; +constexpr int kUsmHostDeallocatedMagic = (char)0x92; +constexpr int kUsmSharedDeallocatedMagic = (char)0x93; +constexpr int kMemBufferDeallocatedMagic = (char)0x93; + +constexpr int kSharedLocalRedzoneMagic = (char)0xa1; + +// Same with host ASan stack +const int kPrivateLeftRedzoneMagic = (char)0xf1; +const int kPrivateMidRedzoneMagic = (char)0xf2; +const int kPrivateRightRedzoneMagic = (char)0xf3; + +constexpr auto kSPIR_AsanShadowMemoryGlobalStart = + "__AsanShadowMemoryGlobalStart"; +constexpr auto kSPIR_AsanShadowMemoryGlobalEnd = "__AsanShadowMemoryGlobalEnd"; + +constexpr auto kSPIR_DeviceType = "__DeviceType"; +constexpr auto kSPIR_AsanDebug = "__AsanDebug"; + +constexpr auto kSPIR_AsanDeviceGlobalCount = "__AsanDeviceGlobalCount"; +constexpr auto kSPIR_AsanDeviceGlobalMetadata = "__AsanDeviceGlobalMetadata"; + inline const char *ToString(DeviceSanitizerMemoryType MemoryType) { switch (MemoryType) { case DeviceSanitizerMemoryType::USM_DEVICE: @@ -94,6 +133,8 @@ inline const char *ToString(DeviceSanitizerErrorType ErrorType) { return "out-of-shadow-bounds-access"; case DeviceSanitizerErrorType::UNKNOWN_DEVICE: return "unknown-device"; + case DeviceSanitizerErrorType::NULL_POINTER: + return "null-pointer-access"; default: return "unknown-error"; } diff --git a/source/loader/layers/sanitizer/asan_quarantine.cpp b/source/loader/layers/sanitizer/asan_quarantine.cpp index 201d828fa3..9826aeb62a 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.cpp +++ b/source/loader/layers/sanitizer/asan_quarantine.cpp @@ -18,8 +18,10 @@ std::vector Quarantine::put(ur_device_handle_t Device, AllocationIterator &It) { auto &AI = It->second; auto AllocSize = AI->AllocSize; - auto &Cache = m_Map[Device]; + auto &Cache = getCache(Device); + std::vector DequeueList; + std::scoped_lock Guard(Cache.Mutex); while (Cache.size() + AllocSize > m_MaxQuarantineSize) { auto ElementOp = Cache.dequeue(); if (!ElementOp) { diff --git a/source/loader/layers/sanitizer/asan_quarantine.hpp b/source/loader/layers/sanitizer/asan_quarantine.hpp index 3f07c62344..0326baed1c 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.hpp +++ b/source/loader/layers/sanitizer/asan_quarantine.hpp @@ -26,7 +26,8 @@ class QuarantineCache { using Element = AllocationIterator; using List = std::queue; - explicit QuarantineCache() {} + // The following methods are not thread safe, use this lock + ur_mutex Mutex; // Total memory used, including internal accounting. uptr size() const { return m_Size; } @@ -62,7 +63,13 @@ class Quarantine { AllocationIterator &Ptr); private: + QuarantineCache &getCache(ur_device_handle_t Device) { + std::scoped_lock Guard(m_Mutex); + return m_Map[Device]; + } + std::unordered_map m_Map; + ur_mutex m_Mutex; size_t m_MaxQuarantineSize; }; diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index 4ba73253dc..5bcf9ca47e 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -11,9 +11,10 @@ */ #include "asan_report.hpp" + #include "asan_allocator.hpp" #include "asan_interceptor.hpp" -#include "device_sanitizer_report.hpp" +#include "asan_libdevice.hpp" #include "ur_sanitizer_layer.hpp" #include "ur_sanitizer_utils.hpp" @@ -35,7 +36,7 @@ void ReportBadFree(uptr Addr, const StackTrace &stack, context.logger.always("{} is located inside of {} region [{}, {})", (void *)Addr, ToString(AI->Type), - (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); + (void *)AI->UserBegin, (void *)AI->UserEnd); context.logger.always("allocated here:"); AI->AllocStack.print(); @@ -51,7 +52,7 @@ void ReportBadContext(uptr Addr, const StackTrace &stack, context.logger.always("{} is located inside of {} region [{}, {})", (void *)Addr, ToString(AI->Type), - (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); + (void *)AI->UserBegin, (void *)AI->UserEnd); context.logger.always("allocated here:"); AI->AllocStack.print(); @@ -72,7 +73,7 @@ void ReportDoubleFree(uptr Addr, const StackTrace &Stack, context.logger.always("{} is located inside of {} region [{}, {})", (void *)Addr, ToString(AI->Type), - (void *)AI->UserBegin, (void *)(AI->UserEnd + 1)); + (void *)AI->UserBegin, (void *)AI->UserEnd); context.logger.always("freed here:"); AI->ReleaseStack.print(); context.logger.always("previously allocated here:"); @@ -120,7 +121,7 @@ void ReportUseAfterFree(const DeviceSanitizerReport &Report, KernelName = DemangleName(KernelName); context.logger.always("\n====ERROR: DeviceSanitizer: {} on address {}", - ToString(Report.ErrorType), (void *)Report.Addr); + ToString(Report.ErrorType), (void *)Report.Address); context.logger.always( "{} of size {} at kernel <{}> LID({}, {}, {}) GID({}, " "{}, {})", @@ -131,24 +132,24 @@ void ReportUseAfterFree(const DeviceSanitizerReport &Report, context.logger.always(""); auto AllocInfoItOp = - context.interceptor->findAllocInfoByAddress(Report.Addr); + context.interceptor->findAllocInfoByAddress(Report.Address); if (!AllocInfoItOp) { context.logger.always("Failed to find which chunck {} is allocated", - (void *)Report.Addr); + (void *)Report.Address); return; } auto &AllocInfo = (*AllocInfoItOp)->second; if (AllocInfo->Context != Context) { context.logger.always("Failed to find which chunck {} is allocated", - (void *)Report.Addr); + (void *)Report.Address); } assert(AllocInfo->IsReleased); context.logger.always("{} is located inside of {} region [{}, {})", - (void *)Report.Addr, ToString(AllocInfo->Type), + (void *)Report.Address, ToString(AllocInfo->Type), (void *)AllocInfo->UserBegin, - (void *)(AllocInfo->UserEnd + 1)); + (void *)AllocInfo->UserEnd); context.logger.always("allocated here:"); AllocInfo->AllocStack.print(); context.logger.always("released here:"); diff --git a/source/loader/layers/sanitizer/common.hpp b/source/loader/layers/sanitizer/common.hpp index ae32941850..974b08e571 100644 --- a/source/loader/layers/sanitizer/common.hpp +++ b/source/loader/layers/sanitizer/common.hpp @@ -28,9 +28,6 @@ using uptr = uintptr_t; using u8 = unsigned char; using u32 = unsigned int; -constexpr unsigned ASAN_SHADOW_SCALE = 3; -constexpr unsigned ASAN_SHADOW_GRANULARITY = 1ULL << ASAN_SHADOW_SCALE; - inline constexpr bool IsPowerOfTwo(uptr x) { return (x & (x - 1)) == 0 && x != 0; } diff --git a/source/loader/layers/sanitizer/ur_sanddi.cpp b/source/loader/layers/sanitizer/ur_sanddi.cpp index 150eca3147..e07329ed5a 100644 --- a/source/loader/layers/sanitizer/ur_sanddi.cpp +++ b/source/loader/layers/sanitizer/ur_sanddi.cpp @@ -58,7 +58,7 @@ __urdlllocal ur_result_t UR_APICALL urUSMHostAlloc( context.logger.debug("==== urUSMHostAlloc"); return context.interceptor->allocateMemory( - hContext, nullptr, pUSMDesc, pool, size, ppMem, AllocType::HOST_USM); + hContext, nullptr, pUSMDesc, pool, size, AllocType::HOST_USM, ppMem); } /////////////////////////////////////////////////////////////////////////////// @@ -83,7 +83,7 @@ __urdlllocal ur_result_t UR_APICALL urUSMDeviceAlloc( context.logger.debug("==== urUSMDeviceAlloc"); return context.interceptor->allocateMemory( - hContext, hDevice, pUSMDesc, pool, size, ppMem, AllocType::DEVICE_USM); + hContext, hDevice, pUSMDesc, pool, size, AllocType::DEVICE_USM, ppMem); } /////////////////////////////////////////////////////////////////////////////// @@ -108,7 +108,7 @@ __urdlllocal ur_result_t UR_APICALL urUSMSharedAlloc( context.logger.debug("==== urUSMSharedAlloc"); return context.interceptor->allocateMemory( - hContext, hDevice, pUSMDesc, pool, size, ppMem, AllocType::SHARED_USM); + hContext, hDevice, pUSMDesc, pool, size, AllocType::SHARED_USM, ppMem); } /////////////////////////////////////////////////////////////////////////////// @@ -214,24 +214,10 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueKernelLaunch( context.logger.debug("==== urEnqueueKernelLaunch"); - LaunchInfo LaunchInfo(GetContext(hQueue)); - const size_t *pUserLocalWorkSize = pLocalWorkSize; - if (!pUserLocalWorkSize) { - pUserLocalWorkSize = LaunchInfo.LocalWorkSize; - // FIXME: This is W/A until urKernelSuggestGroupSize is added - LaunchInfo.LocalWorkSize[0] = 1; - LaunchInfo.LocalWorkSize[1] = 1; - LaunchInfo.LocalWorkSize[2] = 1; - } - - uint32_t numWork = 1; - for (uint32_t dim = 0; dim < workDim; ++dim) { - numWork *= (pGlobalWorkSize[dim] + pUserLocalWorkSize[dim] - 1) / - pUserLocalWorkSize[dim]; - } + LaunchInfo LaunchInfo(GetContext(hQueue), pGlobalWorkSize, pLocalWorkSize, + pGlobalWorkOffset, workDim); - UR_CALL(context.interceptor->preLaunchKernel(hKernel, hQueue, LaunchInfo, - numWork)); + UR_CALL(context.interceptor->preLaunchKernel(hKernel, hQueue, LaunchInfo)); ur_event_handle_t hEvent{}; ur_result_t result = pfnKernelLaunch( @@ -239,8 +225,8 @@ __urdlllocal ur_result_t UR_APICALL urEnqueueKernelLaunch( pLocalWorkSize, numEventsInWaitList, phEventWaitList, &hEvent); if (result == UR_RESULT_SUCCESS) { - context.interceptor->postLaunchKernel(hKernel, hQueue, hEvent, - LaunchInfo); + UR_CALL(context.interceptor->postLaunchKernel(hKernel, hQueue, hEvent, + LaunchInfo)); } if (phEvent) { diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp index a18dc9f89d..394aa09d3f 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.cpp @@ -20,10 +20,19 @@ ManagedQueue::ManagedQueue(ur_context_handle_t Context, [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnCreate(Context, Device, nullptr, &Handle); assert(Result == UR_RESULT_SUCCESS); + context.logger.debug(">>> ManagedQueue {}", (void *)Handle); } ManagedQueue::~ManagedQueue() { - [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnRelease(Handle); + context.logger.debug("<<< ~ManagedQueue {}", (void *)Handle); + + [[maybe_unused]] ur_result_t Result; + Result = context.urDdiTable.Queue.pfnFinish(Handle); + if (Result != UR_RESULT_SUCCESS) { + context.logger.error("Failed to finish ManagedQueue: {}", Result); + } + assert(Result == UR_RESULT_SUCCESS); + Result = context.urDdiTable.Queue.pfnRelease(Handle); assert(Result == UR_RESULT_SUCCESS); } @@ -45,6 +54,15 @@ ur_context_handle_t GetContext(ur_program_handle_t Program) { return Context; } +ur_context_handle_t GetContext(ur_kernel_handle_t Kernel) { + ur_context_handle_t Context{}; + [[maybe_unused]] auto Result = context.urDdiTable.Kernel.pfnGetInfo( + Kernel, UR_KERNEL_INFO_CONTEXT, sizeof(ur_context_handle_t), &Context, + nullptr); + assert(Result == UR_RESULT_SUCCESS && "getContext() failed"); + return Context; +} + ur_device_handle_t GetDevice(ur_queue_handle_t Queue) { ur_device_handle_t Device{}; [[maybe_unused]] auto Result = context.urDdiTable.Queue.pfnGetInfo( @@ -131,4 +149,23 @@ std::vector GetProgramDevices(ur_program_handle_t Program) { return Devices; } +size_t GetKernelNumArgs(ur_kernel_handle_t Kernel) { + size_t NumArgs = 0; + [[maybe_unused]] auto Res = context.urDdiTable.Kernel.pfnGetInfo( + Kernel, UR_KERNEL_INFO_NUM_ARGS, sizeof(NumArgs), &NumArgs, nullptr); + assert(Res == UR_RESULT_SUCCESS); + return NumArgs; +} + +size_t GetVirtualMemGranularity(ur_context_handle_t Context, + ur_device_handle_t Device) { + size_t Size; + [[maybe_unused]] auto Result = + context.urDdiTable.VirtualMem.pfnGranularityGetInfo( + Context, Device, UR_VIRTUAL_MEM_GRANULARITY_INFO_RECOMMENDED, + sizeof(Size), &Size, nullptr); + assert(Result == UR_RESULT_SUCCESS); + return Size; +} + } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp index 47d9d4bf3b..5d82376856 100644 --- a/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp +++ b/source/loader/layers/sanitizer/ur_sanitizer_utils.hpp @@ -32,6 +32,7 @@ struct ManagedQueue { ur_context_handle_t GetContext(ur_queue_handle_t Queue); ur_context_handle_t GetContext(ur_program_handle_t Program); +ur_context_handle_t GetContext(ur_kernel_handle_t Kernel); ur_device_handle_t GetDevice(ur_queue_handle_t Queue); DeviceType GetDeviceType(ur_device_handle_t Device); std::string GetKernelName(ur_kernel_handle_t Kernel); @@ -40,5 +41,8 @@ ur_program_handle_t GetProgram(ur_kernel_handle_t Kernel); std::vector GetProgramDevices(ur_program_handle_t Program); ur_device_handle_t GetUSMAllocDevice(ur_context_handle_t Context, const void *MemPtr); +size_t GetKernelNumArgs(ur_kernel_handle_t Kernel); +size_t GetVirtualMemGranularity(ur_context_handle_t Context, + ur_device_handle_t Device); } // namespace ur_sanitizer_layer From b5e4aa52c073a74fd885ae097f65bbd32d1bdde5 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 27 Mar 2024 04:28:56 -0700 Subject: [PATCH 37/42] fix crash at use-after-free; fix build fail --- source/loader/CMakeLists.txt | 2 +- .../loader/layers/sanitizer/asan_report.cpp | 33 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/source/loader/CMakeLists.txt b/source/loader/CMakeLists.txt index 78a9ed017a..c884607500 100644 --- a/source/loader/CMakeLists.txt +++ b/source/loader/CMakeLists.txt @@ -110,6 +110,7 @@ if(UR_ENABLE_SANITIZER) ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_allocator.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_interceptor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_interceptor.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_libdevice.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_quarantine.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_quarantine.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_report.cpp @@ -117,7 +118,6 @@ if(UR_ENABLE_SANITIZER) ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/asan_shadow_setup.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/common.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/device_sanitizer_report.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/stacktrace.cpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/stacktrace.hpp ${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/ur_sanddi.cpp diff --git a/source/loader/layers/sanitizer/asan_report.cpp b/source/loader/layers/sanitizer/asan_report.cpp index 5bcf9ca47e..56cbbb4b21 100644 --- a/source/loader/layers/sanitizer/asan_report.cpp +++ b/source/loader/layers/sanitizer/asan_report.cpp @@ -136,25 +136,24 @@ void ReportUseAfterFree(const DeviceSanitizerReport &Report, if (!AllocInfoItOp) { context.logger.always("Failed to find which chunck {} is allocated", (void *)Report.Address); - return; + } else { + auto &AllocInfo = (*AllocInfoItOp)->second; + if (AllocInfo->Context != Context) { + context.logger.always("Failed to find which chunck {} is allocated", + (void *)Report.Address); + } + assert(AllocInfo->IsReleased); + + context.logger.always("{} is located inside of {} region [{}, {})", + (void *)Report.Address, ToString(AllocInfo->Type), + (void *)AllocInfo->UserBegin, + (void *)AllocInfo->UserEnd); + context.logger.always("allocated here:"); + AllocInfo->AllocStack.print(); + context.logger.always("released here:"); + AllocInfo->ReleaseStack.print(); } - auto &AllocInfo = (*AllocInfoItOp)->second; - if (AllocInfo->Context != Context) { - context.logger.always("Failed to find which chunck {} is allocated", - (void *)Report.Address); - } - assert(AllocInfo->IsReleased); - - context.logger.always("{} is located inside of {} region [{}, {})", - (void *)Report.Address, ToString(AllocInfo->Type), - (void *)AllocInfo->UserBegin, - (void *)AllocInfo->UserEnd); - context.logger.always("allocated here:"); - AllocInfo->AllocStack.print(); - context.logger.always("released here:"); - AllocInfo->ReleaseStack.print(); - exit(1); } From 8408f4b9d5e0ebc1d0be3917da68e78ff24a0b60 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 27 Mar 2024 04:42:25 -0700 Subject: [PATCH 38/42] sync with latest code --- .../layers/sanitizer/asan_interceptor.cpp | 318 +++++++----------- .../layers/sanitizer/asan_interceptor.hpp | 19 +- 2 files changed, 126 insertions(+), 211 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index c60b9c75b5..bb30987824 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -41,10 +41,106 @@ ur_result_t urEnqueueUSMSet(ur_queue_handle_t Queue, void *Ptr, char Value, size_t Size, uint32_t NumEvents = 0, const ur_event_handle_t *EventWaitList = nullptr, ur_event_handle_t *OutEvent = nullptr) { + if (Size == 0) { + return UR_RESULT_SUCCESS; + } return context.urDdiTable.Enqueue.pfnUSMFill( Queue, Ptr, 1, &Value, Size, NumEvents, EventWaitList, OutEvent); } +ur_result_t enqueueMemSetShadow(ur_context_handle_t Context, + std::shared_ptr &DeviceInfo, + ur_queue_handle_t Queue, uptr Ptr, uptr Size, + u8 Value) { + if (Size == 0) { + return UR_RESULT_SUCCESS; + } + if (DeviceInfo->Type == DeviceType::CPU) { + uptr ShadowBegin = MemToShadow_CPU(DeviceInfo->ShadowOffset, Ptr); + uptr ShadowEnd = + MemToShadow_CPU(DeviceInfo->ShadowOffset, Ptr + Size - 1); + + // Poison shadow memory outside of asan runtime is not allowed, so we + // need to avoid memset's call from being intercepted. + static auto MemSet = + (void *(*)(void *, int, size_t))GetMemFunctionPointer("memset"); + if (!MemSet) { + return UR_RESULT_ERROR_UNKNOWN; + } + context.logger.debug("enqueueMemSetShadow(addr={}, count={}, value={})", + (void *)ShadowBegin, ShadowEnd - ShadowBegin + 1, + (void *)(size_t)Value); + MemSet((void *)ShadowBegin, Value, ShadowEnd - ShadowBegin + 1); + } else if (DeviceInfo->Type == DeviceType::GPU_PVC) { + uptr ShadowBegin = MemToShadow_PVC(DeviceInfo->ShadowOffset, Ptr); + uptr ShadowEnd = + MemToShadow_PVC(DeviceInfo->ShadowOffset, Ptr + Size - 1); + assert(ShadowBegin <= ShadowEnd); + { + static const size_t PageSize = + GetVirtualMemGranularity(Context, DeviceInfo->Handle); + + ur_physical_mem_properties_t Desc{ + UR_STRUCTURE_TYPE_PHYSICAL_MEM_PROPERTIES, nullptr, 0}; + static ur_physical_mem_handle_t PhysicalMem{}; + + // Make sure [Ptr, Ptr + Size] is mapped to physical memory + for (auto MappedPtr = RoundDownTo(ShadowBegin, PageSize); + MappedPtr <= ShadowEnd; MappedPtr += PageSize) { + if (!PhysicalMem) { + auto URes = context.urDdiTable.PhysicalMem.pfnCreate( + Context, DeviceInfo->Handle, PageSize, &Desc, + &PhysicalMem); + if (URes != UR_RESULT_SUCCESS) { + context.logger.error("urPhysicalMemCreate(): {}", URes); + return URes; + } + } + + // context.logger.debug("urVirtualMemMap: {} ~ {}", + // (void *)MappedPtr, + // (void *)(MappedPtr + PageSize - 1)); + + // FIXME: No flag to check the failed reason is VA is already mapped + auto URes = context.urDdiTable.VirtualMem.pfnMap( + Context, (void *)MappedPtr, PageSize, PhysicalMem, 0, + UR_VIRTUAL_MEM_ACCESS_FLAG_READ_WRITE); + // if (URes != UR_RESULT_SUCCESS) { + // context.logger.debug("urVirtualMemMap(): {}", URes); + // } + + // Initialize to zero + if (URes == UR_RESULT_SUCCESS) { + // Reset PhysicalMem to null since it's been mapped + PhysicalMem = nullptr; + + auto URes = + urEnqueueUSMSet(Queue, (void *)MappedPtr, 0, PageSize); + if (URes != UR_RESULT_SUCCESS) { + context.logger.error("urEnqueueUSMFill(): {}", URes); + return URes; + } + } + } + } + + auto URes = urEnqueueUSMSet(Queue, (void *)ShadowBegin, Value, + ShadowEnd - ShadowBegin + 1); + context.logger.debug( + "enqueueMemSetShadow (addr={}, count={}, value={}): {}", + (void *)ShadowBegin, ShadowEnd - ShadowBegin + 1, + (void *)(size_t)Value, URes); + if (URes != UR_RESULT_SUCCESS) { + context.logger.error("urEnqueueUSMFill(): {}", URes); + return URes; + } + } else { + context.logger.error("Unsupport device type"); + return UR_RESULT_ERROR_INVALID_ARGUMENT; + } + return UR_RESULT_SUCCESS; +} + } // namespace SanitizerInterceptor::SanitizerInterceptor() { @@ -320,179 +416,6 @@ ur_result_t DeviceInfo::allocShadowMemory(ur_context_handle_t Context) { return UR_RESULT_SUCCESS; } -ur_result_t SanitizerInterceptor::enqueueMemSetShadow( - ur_context_handle_t Context, std::shared_ptr &DeviceInfo, - ur_queue_handle_t Queue, uptr Ptr, uptr Size, u8 Value) { - - if (DeviceInfo->Type == DeviceType::CPU) { - uptr ShadowBegin = MemToShadow_CPU(DeviceInfo->ShadowOffset, Ptr); - uptr ShadowEnd = - MemToShadow_CPU(DeviceInfo->ShadowOffset, Ptr + Size - 1); - - // Poison shadow memory outside of asan runtime is not allowed, so we - // need to avoid memset's call from being intercepted. - static auto MemSet = - (void *(*)(void *, int, size_t))GetMemFunctionPointer("memset"); - if (!MemSet) { - return UR_RESULT_ERROR_UNKNOWN; - } - - MemSet((void *)ShadowBegin, Value, ShadowEnd - ShadowBegin + 1); - context.logger.debug("enqueueMemSetShadow(addr={}, count={}, value={})", - (void *)ShadowBegin, ShadowEnd - ShadowBegin + 1, - (void *)(size_t)Value); - } else if (DeviceInfo->Type == DeviceType::GPU_PVC) { - uptr ShadowBegin = MemToShadow_PVC(DeviceInfo->ShadowOffset, Ptr); - uptr ShadowEnd = - MemToShadow_PVC(DeviceInfo->ShadowOffset, Ptr + Size - 1); - - { - static const size_t PageSize = - GetVirtualMemGranularity(Context, DeviceInfo->Handle); - - ur_physical_mem_properties_t Desc{ - UR_STRUCTURE_TYPE_PHYSICAL_MEM_PROPERTIES, nullptr, 0}; - static ur_physical_mem_handle_t PhysicalMem{}; - - // Make sure [Ptr, Ptr + Size] is mapped to physical memory - for (auto MappedPtr = RoundDownTo(ShadowBegin, PageSize); - MappedPtr <= ShadowEnd; MappedPtr += PageSize) { - if (!PhysicalMem) { - auto URes = context.urDdiTable.PhysicalMem.pfnCreate( - Context, DeviceInfo->Handle, PageSize, &Desc, - &PhysicalMem); - if (URes != UR_RESULT_SUCCESS) { - context.logger.error("urPhysicalMemCreate(): {}", URes); - return URes; - } - } - - context.logger.debug("urVirtualMemMap: {} ~ {}", - (void *)MappedPtr, - (void *)(MappedPtr + PageSize - 1)); - - // FIXME: No flag to check the failed reason is VA is already mapped - auto URes = context.urDdiTable.VirtualMem.pfnMap( - Context, (void *)MappedPtr, PageSize, PhysicalMem, 0, - UR_VIRTUAL_MEM_ACCESS_FLAG_READ_WRITE); - if (URes != UR_RESULT_SUCCESS) { - context.logger.debug("urVirtualMemMap(): {}", URes); - } - - // Initialize to zero - if (URes == UR_RESULT_SUCCESS) { - // Reset PhysicalMem to null since it's been mapped - PhysicalMem = nullptr; - - auto URes = - urEnqueueUSMSet(Queue, (void *)MappedPtr, 0, PageSize); - if (URes != UR_RESULT_SUCCESS) { - context.logger.error("urEnqueueUSMFill(): {}", URes); - return URes; - } - } - } - } - - auto URes = urEnqueueUSMSet(Queue, (void *)ShadowBegin, Value, - ShadowEnd - ShadowBegin + 1); - context.logger.debug( - "enqueueMemSetShadow (addr={}, count={}, value={}): {}", - (void *)ShadowBegin, ShadowEnd - ShadowBegin + 1, - (void *)(size_t)Value, URes); - if (URes != UR_RESULT_SUCCESS) { - context.logger.error("urEnqueueUSMFill(): {}", URes); - return URes; - } - } else { - context.logger.error("Unsupport device type"); - return UR_RESULT_ERROR_INVALID_ARGUMENT; - } - return UR_RESULT_SUCCESS; -} - -/// Each 8 bytes of application memory are mapped into one byte of shadow memory -/// The meaning of that byte: -/// - Negative: All bytes are not accessible (poisoned) -/// - 0: All bytes are accessible -/// - 1 <= k <= 7: Only the first k bytes is accessible -/// -/// ref: https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm#mapping -ur_result_t SanitizerInterceptor::enqueueAllocInfo( - ur_context_handle_t Context, std::shared_ptr &DeviceInfo, - ur_queue_handle_t Queue, std::shared_ptr &AI) { - if (AI->IsReleased) { - int ShadowByte; - switch (AI->Type) { - case AllocType::HOST_USM: - ShadowByte = kUsmHostDeallocatedMagic; - break; - case AllocType::DEVICE_USM: - ShadowByte = kUsmDeviceDeallocatedMagic; - break; - case AllocType::SHARED_USM: - ShadowByte = kUsmSharedDeallocatedMagic; - break; - case AllocType::MEM_BUFFER: - ShadowByte = kMemBufferDeallocatedMagic; - break; - default: - ShadowByte = 0xff; - assert(false && "Unknow AllocInfo Type"); - } - UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AI->AllocBegin, - AI->AllocSize, ShadowByte)); - return UR_RESULT_SUCCESS; - } - - // Init zero - UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AI->AllocBegin, - AI->AllocSize, 0)); - - uptr TailBegin = RoundUpTo(AI->UserEnd, ASAN_SHADOW_GRANULARITY); - uptr TailEnd = AI->AllocBegin + AI->AllocSize; - - // User tail - if (TailBegin != AI->UserEnd) { - auto Value = - AI->UserEnd - RoundDownTo(AI->UserEnd, ASAN_SHADOW_GRANULARITY); - UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AI->UserEnd, 1, - static_cast(Value))); - } - - int ShadowByte; - switch (AI->Type) { - case AllocType::HOST_USM: - ShadowByte = kUsmHostRedzoneMagic; - break; - case AllocType::DEVICE_USM: - ShadowByte = kUsmDeviceRedzoneMagic; - break; - case AllocType::SHARED_USM: - ShadowByte = kUsmSharedRedzoneMagic; - break; - case AllocType::MEM_BUFFER: - ShadowByte = kMemBufferRedzoneMagic; - break; - case AllocType::DEVICE_GLOBAL: - ShadowByte = kDeviceGlobalRedzoneMagic; - break; - default: - ShadowByte = 0xff; - assert(false && "Unknow AllocInfo Type"); - } - - // Left red zone - UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AI->AllocBegin, - AI->UserBegin - AI->AllocBegin, ShadowByte)); - - // Right red zone - UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, TailBegin, - TailEnd - TailBegin, ShadowByte)); - - return UR_RESULT_SUCCESS; -} - ur_result_t SanitizerInterceptor::updateShadowMemory( std::shared_ptr &ContextInfo, std::shared_ptr &DeviceInfo, ur_queue_handle_t Queue) { @@ -628,19 +551,20 @@ ur_result_t SanitizerInterceptor::prepareLaunch( do { // Write global variable to program - auto EnqueueWriteGlobal = - [Queue, Program](const char *Name, const void *Value, size_t Size) { - auto Result = - context.urDdiTable.Enqueue.pfnDeviceGlobalVariableWrite( - Queue, Program, Name, false, Size, 0, Value, 0, nullptr, - nullptr); - if (Result != UR_RESULT_SUCCESS) { - context.logger.warning("Device Global[{}] Write Failed: {}", - Name, Result); - return false; - } - return true; - }; + auto EnqueueWriteGlobal = [Queue, Program](const char *Name, + const void *Value, + size_t Size) { + auto Result = + context.urDdiTable.Enqueue.pfnDeviceGlobalVariableWrite( + Queue, Program, Name, false, Size, 0, Value, 0, nullptr, + nullptr); + if (Result != UR_RESULT_SUCCESS) { + context.logger.warning( + "Failed to write device global \"{}\": {}", Name, Result); + return false; + } + return true; + }; // Write debug EnqueueWriteGlobal(kSPIR_AsanDebug, &cl_Debug, sizeof(cl_Debug)); @@ -741,30 +665,14 @@ SanitizerInterceptor::findAllocInfoByAddress(uptr Address) { return --It; } -LaunchInfo::LaunchInfo(ur_context_handle_t Context, - const size_t *GlobalWorkSize, - const size_t *LocalWorkSize, - const size_t *GlobalWorkOffset, uint32_t WorkDim) - : Context(Context), GlobalWorkSize(GlobalWorkSize), - GlobalWorkOffset(GlobalWorkOffset), WorkDim(WorkDim) { - [[maybe_unused]] auto Result = - context.urDdiTable.Context.pfnRetain(Context); - assert(Result == UR_RESULT_SUCCESS); - - if (LocalWorkSize) { - this->LocalWorkSize = - std::vector(LocalWorkSize, LocalWorkSize + WorkDim); - } -} - LaunchInfo::~LaunchInfo() { + [[maybe_unused]] ur_result_t Result; if (LocalShadowOffset) { - [[maybe_unused]] auto Result = + Result = context.urDdiTable.USM.pfnFree(Context, (void *)LocalShadowOffset); assert(Result == UR_RESULT_SUCCESS); } - [[maybe_unused]] auto Result = - context.urDdiTable.Context.pfnRelease(Context); + Result = context.urDdiTable.Context.pfnRelease(Context); assert(Result == UR_RESULT_SUCCESS); } diff --git a/source/loader/layers/sanitizer/asan_interceptor.hpp b/source/loader/layers/sanitizer/asan_interceptor.hpp index 6d2fd79188..a691bee7b7 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.hpp +++ b/source/loader/layers/sanitizer/asan_interceptor.hpp @@ -120,7 +120,17 @@ struct LaunchInfo { LaunchInfo(ur_context_handle_t Context, const size_t *GlobalWorkSize, const size_t *LocalWorkSize, const size_t *GlobalWorkOffset, - uint32_t WorkDim); + uint32_t WorkDim) + : Context(Context), GlobalWorkSize(GlobalWorkSize), + GlobalWorkOffset(GlobalWorkOffset), WorkDim(WorkDim) { + [[maybe_unused]] auto Result = + context.urDdiTable.Context.pfnRetain(Context); + assert(Result == UR_RESULT_SUCCESS); + if (LocalWorkSize) { + this->LocalWorkSize = + std::vector(LocalWorkSize, LocalWorkSize + WorkDim); + } + } ~LaunchInfo(); }; @@ -189,10 +199,6 @@ class SanitizerInterceptor { ur_result_t allocShadowMemory(ur_context_handle_t Context, std::shared_ptr &DeviceInfo); - ur_result_t enqueueMemSetShadow(ur_context_handle_t Context, - std::shared_ptr &DeviceInfo, - ur_queue_handle_t Queue, uptr Addr, - uptr Size, u8 Value); std::shared_ptr getDeviceInfo(ur_device_handle_t Device) { std::shared_lock Guard(m_DeviceMapMutex); @@ -209,10 +215,11 @@ class SanitizerInterceptor { m_DeviceMap; ur_shared_mutex m_DeviceMapMutex; - /// Assumption: all usm chunks are allocated in one VA + /// Assumption: all USM chunks are allocated in one VA AllocationMap m_AllocationMap; ur_shared_mutex m_AllocationMapMutex; + // We use "uint64_t" here because EnqueueWriteGlobal will fail when it's "uint32_t" uint64_t cl_Debug = 0; uint32_t cl_MaxQuarantineSizeMB = 0; bool cl_DetectLocals = true; From d698d333b1337509209239c320d2a24762646edf Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 27 Mar 2024 05:11:00 -0700 Subject: [PATCH 39/42] fix build --- .../layers/sanitizer/asan_interceptor.cpp | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index bb30987824..befa678b7e 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -416,6 +416,88 @@ ur_result_t DeviceInfo::allocShadowMemory(ur_context_handle_t Context) { return UR_RESULT_SUCCESS; } +/// Each 8 bytes of application memory are mapped into one byte of shadow memory +/// The meaning of that byte: +/// - Negative: All bytes are not accessible (poisoned) +/// - 0: All bytes are accessible +/// - 1 <= k <= 7: Only the first k bytes is accessible +/// +/// ref: https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm#mapping +ur_result_t SanitizerInterceptor::enqueueAllocInfo( + ur_context_handle_t Context, std::shared_ptr &DeviceInfo, + ur_queue_handle_t Queue, std::shared_ptr &AI) { + if (AI->IsReleased) { + int ShadowByte; + switch (AI->Type) { + case AllocType::HOST_USM: + ShadowByte = kUsmHostDeallocatedMagic; + break; + case AllocType::DEVICE_USM: + ShadowByte = kUsmDeviceDeallocatedMagic; + break; + case AllocType::SHARED_USM: + ShadowByte = kUsmSharedDeallocatedMagic; + break; + case AllocType::MEM_BUFFER: + ShadowByte = kMemBufferDeallocatedMagic; + break; + default: + ShadowByte = 0xff; + assert(false && "Unknow AllocInfo Type"); + } + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AI->AllocBegin, + AI->AllocSize, ShadowByte)); + return UR_RESULT_SUCCESS; + } + + // Init zero + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AI->AllocBegin, + AI->AllocSize, 0)); + + uptr TailBegin = RoundUpTo(AI->UserEnd, ASAN_SHADOW_GRANULARITY); + uptr TailEnd = AI->AllocBegin + AI->AllocSize; + + // User tail + if (TailBegin != AI->UserEnd) { + auto Value = + AI->UserEnd - RoundDownTo(AI->UserEnd, ASAN_SHADOW_GRANULARITY); + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AI->UserEnd, 1, + static_cast(Value))); + } + + int ShadowByte; + switch (AI->Type) { + case AllocType::HOST_USM: + ShadowByte = kUsmHostRedzoneMagic; + break; + case AllocType::DEVICE_USM: + ShadowByte = kUsmDeviceRedzoneMagic; + break; + case AllocType::SHARED_USM: + ShadowByte = kUsmSharedRedzoneMagic; + break; + case AllocType::MEM_BUFFER: + ShadowByte = kMemBufferRedzoneMagic; + break; + case AllocType::DEVICE_GLOBAL: + ShadowByte = kDeviceGlobalRedzoneMagic; + break; + default: + ShadowByte = 0xff; + assert(false && "Unknow AllocInfo Type"); + } + + // Left red zone + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, AI->AllocBegin, + AI->UserBegin - AI->AllocBegin, ShadowByte)); + + // Right red zone + UR_CALL(enqueueMemSetShadow(Context, DeviceInfo, Queue, TailBegin, + TailEnd - TailBegin, ShadowByte)); + + return UR_RESULT_SUCCESS; +} + ur_result_t SanitizerInterceptor::updateShadowMemory( std::shared_ptr &ContextInfo, std::shared_ptr &DeviceInfo, ur_queue_handle_t Queue) { From 611a87218998236dcd56f1fa07bf2f91382c9258 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 27 Mar 2024 05:20:41 -0700 Subject: [PATCH 40/42] remove RunCommand --- source/loader/layers/sanitizer/common.hpp | 2 -- .../layers/sanitizer/linux/sanitizer_utils.cpp | 13 ------------- 2 files changed, 15 deletions(-) diff --git a/source/loader/layers/sanitizer/common.hpp b/source/loader/layers/sanitizer/common.hpp index 974b08e571..d5612100aa 100644 --- a/source/loader/layers/sanitizer/common.hpp +++ b/source/loader/layers/sanitizer/common.hpp @@ -100,6 +100,4 @@ void *GetMemFunctionPointer(const char *); std::string DemangleName(const std::string &name); -std::string RunCommand(const char *cmd); - } // namespace ur_sanitizer_layer diff --git a/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp b/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp index 430bcc4c8a..63718207ba 100644 --- a/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp +++ b/source/loader/layers/sanitizer/linux/sanitizer_utils.cpp @@ -69,17 +69,4 @@ std::string DemangleName(const std::string &name) { return result; } -std::string RunCommand(const char *cmd) { - std::array buffer; - std::string result; - std::unique_ptr pipe(popen(cmd, "r"), pclose); - if (!pipe) { - throw std::runtime_error("popen() failed!"); - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; -} - } // namespace ur_sanitizer_layer From 7a90ab63771cf8a082c7eedd9ff846819769fb8b Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 27 Mar 2024 05:40:17 -0700 Subject: [PATCH 41/42] clean code --- .../layers/sanitizer/asan_interceptor.cpp | 18 +++++++++--------- .../loader/layers/sanitizer/asan_libdevice.hpp | 4 ---- .../layers/sanitizer/asan_quarantine.hpp | 2 -- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index befa678b7e..7cf36c0d71 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -97,17 +97,17 @@ ur_result_t enqueueMemSetShadow(ur_context_handle_t Context, } } - // context.logger.debug("urVirtualMemMap: {} ~ {}", - // (void *)MappedPtr, - // (void *)(MappedPtr + PageSize - 1)); + context.logger.debug("urVirtualMemMap: {} ~ {}", + (void *)MappedPtr, + (void *)(MappedPtr + PageSize - 1)); // FIXME: No flag to check the failed reason is VA is already mapped auto URes = context.urDdiTable.VirtualMem.pfnMap( Context, (void *)MappedPtr, PageSize, PhysicalMem, 0, UR_VIRTUAL_MEM_ACCESS_FLAG_READ_WRITE); - // if (URes != UR_RESULT_SUCCESS) { - // context.logger.debug("urVirtualMemMap(): {}", URes); - // } + if (URes != UR_RESULT_SUCCESS) { + context.logger.debug("urVirtualMemMap(): {}", URes); + } // Initialize to zero if (URes == UR_RESULT_SUCCESS) { @@ -173,7 +173,7 @@ SanitizerInterceptor::SanitizerInterceptor() { KV = Options->find("detect_locals"); if (KV != Options->end()) { auto Value = KV->second.front(); - cl_DetectLocals = Value == "1" || Value == "true" ? 1 : 0; + cl_DetectLocals = Value == "1" || Value == "true" ? true : false; } } @@ -576,7 +576,7 @@ SanitizerInterceptor::insertContext(ur_context_handle_t Context, CI = std::make_shared(Context); - m_ContextMap.emplace(Context, CI); + m_ContextMap.emplace(Context, std::move(CI)); return UR_RESULT_SUCCESS; } @@ -612,7 +612,7 @@ SanitizerInterceptor::insertDevice(ur_device_handle_t Device, Device, UR_DEVICE_INFO_MEM_BASE_ADDR_ALIGN, sizeof(DI->Alignment), &DI->Alignment, nullptr)); - m_DeviceMap.emplace(Device, DI); + m_DeviceMap.emplace(Device, std::move(DI)); return UR_RESULT_SUCCESS; } diff --git a/source/loader/layers/sanitizer/asan_libdevice.hpp b/source/loader/layers/sanitizer/asan_libdevice.hpp index ea2ffd8fe4..46ddee4423 100644 --- a/source/loader/layers/sanitizer/asan_libdevice.hpp +++ b/source/loader/layers/sanitizer/asan_libdevice.hpp @@ -65,10 +65,6 @@ struct DeviceSanitizerReport { constexpr unsigned ASAN_SHADOW_SCALE = 3; constexpr unsigned ASAN_SHADOW_GRANULARITY = 1ULL << ASAN_SHADOW_SCALE; -// Based on the observation, only the last 24 bits of the address of the private -// variable have changed, we use 31 bits(2G) to be safe. -constexpr std::size_t ASAN_PRIVATE_SIZE = 0x7fffffffULL + 1; - // These magic values are written to shadow for better error // reporting. constexpr int kUsmDeviceRedzoneMagic = (char)0x81; diff --git a/source/loader/layers/sanitizer/asan_quarantine.hpp b/source/loader/layers/sanitizer/asan_quarantine.hpp index 0326baed1c..6dc15d382a 100644 --- a/source/loader/layers/sanitizer/asan_quarantine.hpp +++ b/source/loader/layers/sanitizer/asan_quarantine.hpp @@ -47,8 +47,6 @@ class QuarantineCache { return It; } - void printStats() const {} - private: List m_List; std::atomic_uintptr_t m_Size = 0; From a8ae97ee71c58f3c8682c2c76b4d97e8e1086137 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 2 Apr 2024 21:05:04 -0700 Subject: [PATCH 42/42] fix crash --- source/loader/layers/sanitizer/asan_interceptor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/loader/layers/sanitizer/asan_interceptor.cpp b/source/loader/layers/sanitizer/asan_interceptor.cpp index 7cf36c0d71..c55d752410 100644 --- a/source/loader/layers/sanitizer/asan_interceptor.cpp +++ b/source/loader/layers/sanitizer/asan_interceptor.cpp @@ -576,7 +576,8 @@ SanitizerInterceptor::insertContext(ur_context_handle_t Context, CI = std::make_shared(Context); - m_ContextMap.emplace(Context, std::move(CI)); + // Don't move CI, since it's a return value as well + m_ContextMap.emplace(Context, CI); return UR_RESULT_SUCCESS; } @@ -612,7 +613,8 @@ SanitizerInterceptor::insertDevice(ur_device_handle_t Device, Device, UR_DEVICE_INFO_MEM_BASE_ADDR_ALIGN, sizeof(DI->Alignment), &DI->Alignment, nullptr)); - m_DeviceMap.emplace(Device, std::move(DI)); + // Don't move DI, since it's a return value as well + m_DeviceMap.emplace(Device, DI); return UR_RESULT_SUCCESS; }