Skip to content

Commit

Permalink
Merge pull request oneapi-src#1844 from zhaomaosu/implement-symbolizer
Browse files Browse the repository at this point in the history
[DeviceSanitizer] Implement symbolizer for more readable information
  • Loading branch information
omarahmed1111 committed Jul 29, 2024
2 parents 2e6c1de + dac2a0f commit 0f4e47e
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 3 deletions.
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
cmake_minimum_required(VERSION 3.20.0 FATAL_ERROR)
project(unified-runtime VERSION 0.10.0)

# Check if unified runtime is built as a standalone project.
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR UR_STANDALONE_BUILD)
set(UR_STANDALONE_BUILD TRUE)
endif()

include(GNUInstallDirs)
include(CheckCXXSourceCompiles)
include(CMakePackageConfigHelpers)
Expand Down Expand Up @@ -37,6 +42,7 @@ option(UR_USE_MSAN "enable MemorySanitizer" OFF)
option(UR_USE_TSAN "enable ThreadSanitizer" OFF)
option(UR_ENABLE_TRACING "enable api tracing through xpti" OFF)
option(UR_ENABLE_SANITIZER "enable device sanitizer" ON)
option(UR_ENABLE_SYMBOLIZER "enable symoblizer for sanitizer" OFF)
option(UMF_BUILD_SHARED_LIBRARY "Build UMF as shared library" ON)
option(UMF_ENABLE_POOL_TRACKING "Build UMF with pool tracking" ON)
option(UR_BUILD_ADAPTER_L0 "Build the Level-Zero adapter" OFF)
Expand Down Expand Up @@ -163,6 +169,14 @@ if(UR_ENABLE_SANITIZER)
else()
add_compile_definitions(UR_ENABLE_SANITIZER)
endif()

if(UR_ENABLE_SYMBOLIZER AND UR_STANDALONE_BUILD)
find_package(LLVM REQUIRED)
endif()
else()
if(UR_ENABLE_SYMBOLIZER)
message(FATAL_ERROR "Symbolizer must be enabled with Sanitizer layer")
endif()
endif()

if(UR_USE_ASAN)
Expand Down
9 changes: 9 additions & 0 deletions source/loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,15 @@ if(UR_ENABLE_SANITIZER)
${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/sanitizer_utils.cpp
)

if(UR_ENABLE_SYMBOLIZER)
target_sources(ur_loader
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer/linux/symbolizer.cpp
)
target_include_directories(ur_loader PRIVATE ${LLVM_INCLUDE_DIRS})
target_link_libraries(ur_loader PRIVATE LLVMSymbolize)
endif()

target_include_directories(ur_loader PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/layers/sanitizer"
"${CMAKE_CURRENT_SOURCE_DIR}/../"
Expand Down
4 changes: 2 additions & 2 deletions source/loader/layers/sanitizer/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ using BacktraceInfo = std::string;
struct SourceInfo {
std::string file;
std::string function;
int line;
int column;
int line = 0;
int column = 0;
};

enum class DeviceType : uint64_t { UNKNOWN = 0, CPU, GPU_PVC, GPU_DG2 };
Expand Down
2 changes: 1 addition & 1 deletion source/loader/layers/sanitizer/linux/backtrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ StackTrace GetCurrentBacktrace() {
StackTrace Stack;
for (int i = 0; i < FrameCount; i++) {
BacktraceInfo addr_info(Symbols[i]);
Stack.stack.emplace_back(std::move(addr_info));
Stack.stack.emplace_back(addr_info);
}
free(Symbols);

Expand Down
60 changes: 60 additions & 0 deletions source/loader/layers/sanitizer/linux/symbolizer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
*
* 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
*
*/
#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"

namespace ur_sanitizer_layer {

llvm::symbolize::LLVMSymbolizer *GetSymbolizer() {
static llvm::symbolize::LLVMSymbolizer Symbolizer;
return &Symbolizer;
}

llvm::symbolize::PrinterConfig GetPrinterConfig() {
llvm::symbolize::PrinterConfig Config;
Config.Pretty = false;
Config.PrintAddress = false;
Config.PrintFunctions = true;
Config.SourceContextLines = 0;
Config.Verbose = false;
return Config;
}

} // namespace ur_sanitizer_layer

extern "C" {

bool SymbolizeCode(const std::string ModuleName, uint64_t ModuleOffset,
std::string &Result) {
llvm::raw_string_ostream OS(Result);
llvm::symbolize::Request Request{ModuleName, ModuleOffset};
llvm::symbolize::PrinterConfig Config =
ur_sanitizer_layer::GetPrinterConfig();
llvm::symbolize::ErrorHandler EH = [&](const llvm::ErrorInfoBase &ErrorInfo,
llvm::StringRef ErrorBanner) {
OS << ErrorBanner;
ErrorInfo.log(OS);
OS << '\n';
};
auto Printer =
std::make_unique<llvm::symbolize::LLVMPrinter>(OS, EH, Config);

auto ResOrErr = ur_sanitizer_layer::GetSymbolizer()->symbolizeInlinedCode(
ModuleName,
{ModuleOffset, llvm::object::SectionedAddress::UndefSection});

if (!ResOrErr) {
return false;
}
Printer->print(Request, *ResOrErr);
ur_sanitizer_layer::GetSymbolizer()->pruneCache();
return true;
}
}
75 changes: 75 additions & 0 deletions source/loader/layers/sanitizer/stacktrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
#include "stacktrace.hpp"
#include "ur_sanitizer_layer.hpp"

extern "C" {

__attribute__((weak)) bool SymbolizeCode(const std::string ModuleName,
uint64_t ModuleOffset,
std::string &Result);
}

namespace ur_sanitizer_layer {

namespace {
Expand All @@ -21,6 +28,54 @@ bool Contains(const std::string &s, const char *p) {
return s.find(p) != std::string::npos;
}

// Parse back trace information in the following formats:
// <module_name>([function_name]+function_offset) [offset]
void ParseBacktraceInfo(BacktraceInfo BI, std::string &ModuleName,
uptr &Offset) {
// Parse module name
size_t End = BI.find_first_of('(');
assert(End != std::string::npos);
ModuleName = BI.substr(0, End);
// Parse offset
size_t Start = BI.find_first_of('[');
assert(Start != std::string::npos);
Start = BI.substr(Start + 1, 2) == "0x" ? Start + 3 : Start + 1;
End = BI.find_first_of(']');
assert(End != std::string::npos);
Offset = std::stoull(BI.substr(Start, End), nullptr, 16);
return;
}

// Parse symbolizer output in the following formats:
// <function_name>
// <file_name>:<line_number>[:<column_number>]
SourceInfo ParseSymbolizerOutput(std::string Output) {
SourceInfo Info;
// Parse function name
size_t End = Output.find_first_of('\n');
assert(End != std::string::npos);
Info.function = Output.substr(0, End);
// Parse file name
size_t Start = End + 1;
End = Output.find_first_of(':', Start);
assert(End != std::string::npos);
Info.file = Output.substr(Start, End - Start);
// Parse line number
Start = End + 1;
End = Output.find_first_of(":\n", Start);
assert(End != std::string::npos);
Info.line = std::stoi(Output.substr(Start, End - Start));
// Parse column number if exists
if (Output[End] == ':') {
Start = End + 1;
End = Output.find_first_of("\n", Start);
assert(End != std::string::npos);
Info.column = std::stoi(Output.substr(Start, End - Start));
}

return Info;
}

} // namespace

void StackTrace::print() const {
Expand All @@ -37,6 +92,26 @@ void StackTrace::print() const {
Contains(BI, "libur_loader.so")) {
continue;
}

if (&SymbolizeCode != nullptr) {
std::string Result;
std::string ModuleName;
uptr Offset;
ParseBacktraceInfo(BI, ModuleName, Offset);
if (SymbolizeCode(ModuleName, Offset, Result)) {
SourceInfo SrcInfo = ParseSymbolizerOutput(Result);
if (SrcInfo.file != "??") {
getContext()->logger.always(" #{} in {} {}:{}:{}", index,
SrcInfo.function, SrcInfo.file,
SrcInfo.line, SrcInfo.column);
} else {
getContext()->logger.always(" #{} in {} ({}+{})", index,
SrcInfo.function, ModuleName,
(void *)Offset);
}
continue;
}
}
getContext()->logger.always(" #{} {}", index, BI);
++index;
}
Expand Down

0 comments on commit 0f4e47e

Please sign in to comment.