diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a77d2b1ff..58d27759a1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -121,8 +121,28 @@ foreach(header ${GENERATED_HEADERS}) COMPONENT runtime) endforeach() +## Build the util library +file(GLOB UTIL_SOURCES "util/*.cpp") +add_library(util STATIC ${UTIL_SOURCES}) + +set_target_properties(util PROPERTIES POSITION_INDEPENDENT_CODE ON) + +target_include_directories(util + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/util) + +check_include_file(backtrace.h BACKTRACE_H) +if(BACKTRACE_H) + target_compile_definitions(util PRIVATE HAVE_BACKTRACE_H) + find_library(BACKTRACE_LIB "backtrace" ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) +endif() + +if(BACKTRACE_LIB) + target_compile_definitions(util PRIVATE ENABLE_BACKTRACE) + target_link_libraries(util PRIVATE ${BACKTRACE_LIB}) +endif() + ## Build the ROCtracer library -file(GLOB ROCTRACER_SOURCES "roctracer/*.cpp" "util/*.cpp") +file(GLOB ROCTRACER_SOURCES "roctracer/*.cpp") add_library(roctracer ${LIBRARY_TYPE} ${ROCTRACER_SOURCES} ${GENERATED_HEADERS} hsa_prof_str.inline.h) set_target_properties(roctracer PROPERTIES @@ -146,7 +166,7 @@ target_include_directories(roctracer ${CMAKE_CURRENT_SOURCE_DIR}/roctracer ${CMAKE_CURRENT_SOURCE_DIR}) target_link_options(roctracer PRIVATE -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/roctracer/exportmap -Wl,--no-undefined) -target_link_libraries(roctracer PRIVATE hsa-runtime64::hsa-runtime64 Threads::Threads dl) +target_link_libraries(roctracer PRIVATE util hsa-runtime64::hsa-runtime64 Threads::Threads dl) install(TARGETS roctracer LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -177,7 +197,7 @@ install(TARGETS roctx LIBRARY ## Build the tracer_tool library if (${LIBRARY_TYPE} STREQUAL SHARED) -file(GLOB TRACER_TOOL_SOURCES "tracer_tool/*.cpp" "util/*.cpp") +file(GLOB TRACER_TOOL_SOURCES "tracer_tool/*.cpp") add_library(roctracer_tool SHARED ${TRACER_TOOL_SOURCES}) set_target_properties(roctracer_tool PROPERTIES @@ -192,7 +212,7 @@ target_include_directories(roctracer_tool ${PROJECT_SOURCE_DIR}/inc ${CMAKE_CURRENT_SOURCE_DIR}/roctracer ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(roctracer_tool roctracer hsa-runtime64::hsa-runtime64 stdc++fs Threads::Threads atomic dl) +target_link_libraries(roctracer_tool util roctracer hsa-runtime64::hsa-runtime64 stdc++fs Threads::Threads atomic dl) target_link_options(roctracer_tool PRIVATE -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/tracer_tool/exportmap -Wl,--no-undefined) install(TARGETS roctracer_tool LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} COMPONENT runtime) diff --git a/src/util/debug.cpp b/src/util/debug.cpp new file mode 100644 index 0000000000..46c2ab8d00 --- /dev/null +++ b/src/util/debug.cpp @@ -0,0 +1,117 @@ +/* Copyright (c) 2022 Advanced Micro Devices, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#include "debug.h" +#include "util.h" + +#include +#include +#include +#include +#include + +#if defined(ENABLE_BACKTRACE) + +#include +#include + +namespace { + +struct BackTraceInfo { + struct ::backtrace_state* state = nullptr; + std::stringstream sstream{}; + int depth = 0; + int error = 0; +}; + +void errorCallback(void* data, const char* message, int errnum) { + BackTraceInfo* info = static_cast(data); + info->sstream << "Error: " << message << '(' << errnum << ')'; + info->error = 1; +} + +void syminfoCallback(void* data, uintptr_t /* pc */, const char* symname, uintptr_t /* symval */, + uintptr_t /* symsize */) { + BackTraceInfo* info = static_cast(data); + + if (symname == nullptr) return; + + int status; + char* demangled = abi::__cxa_demangle(symname, nullptr, nullptr, &status); + info->sstream << ' ' << (status == 0 ? demangled : symname); + free(demangled); +} + +int fullCallback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function) { + BackTraceInfo* info = static_cast(data); + + info->sstream << std::endl + << " #" << std::dec << info->depth++ << ' ' << std::showbase << std::hex + << std::setfill('0') << std::setw(sizeof(pc) * 2) << pc; + if (function == nullptr) + backtrace_syminfo(info->state, pc, syminfoCallback, errorCallback, data); + else { + int status; + char* demangled = abi::__cxa_demangle(function, nullptr, nullptr, &status); + info->sstream << ' ' << (status == 0 ? demangled : function); + free(demangled); + + if (filename != nullptr) { + info->sstream << " in " << filename; + if (lineno) info->sstream << ':' << std::dec << lineno; + } + } + + return info->error; +} + +} // namespace +#endif // defined (ENABLE_BACKTRACE) + +namespace roctracer { + +void warning(const char* format, ...) { + va_list va; + va_start(va, format); + std::cerr << "Warning: " << string_vprintf(format, va) << std::endl; + va_end(va); +} + +void fatal [[noreturn]] (const char* format, ...) { + va_list va; + va_start(va, format); + std::string message = string_vprintf(format, va); + va_end(va); + +#if defined(ENABLE_BACKTRACE) + BackTraceInfo info; + + info.sstream << std::endl << "Backtrace:"; + info.state = ::backtrace_create_state("/proc/self/exe", 0, errorCallback, &info); + ::backtrace_full(info.state, 1, fullCallback, errorCallback, &info); + + message += info.sstream.str(); +#endif /* defined (ENABLE_BACKTRACE) */ + + std::cerr << "Error: " << message << std::endl; + abort(); +} + +} // namespace roctracer \ No newline at end of file diff --git a/src/util/debug.h b/src/util/debug.h new file mode 100644 index 0000000000..9e295c1b27 --- /dev/null +++ b/src/util/debug.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2022 Advanced Micro Devices, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#pragma once + +namespace roctracer { + +extern void warning(const char* format, ...) +#if defined(__GNUC__) + __attribute__((format(printf, 1, 2))) +#endif // defined (__GNUC__) + ; + +extern void fatal [[noreturn]] (const char* format, ...) +#if defined(__GNUC__) +__attribute__((format(printf, 1, 2))) +#endif // defined (__GNUC__) +; + +} // namespace roctracer diff --git a/src/util/util.cpp b/src/util/util.cpp new file mode 100644 index 0000000000..61e7296156 --- /dev/null +++ b/src/util/util.cpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2022 Advanced Micro Devices, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#include "util.h" + +#include +#include +#include + +namespace roctracer { + +std::string string_vprintf(const char* format, va_list va) { + va_list copy; + + va_copy(copy, va); + size_t size = vsnprintf(NULL, 0, format, copy); + va_end(copy); + + std::string str(size, '\0'); + vsprintf(&str[0], format, va); + + return str; +} + +std::string string_printf(const char* format, ...) { + va_list va; + va_start(va, format); + std::string str(string_vprintf(format, va)); + va_end(va); + + return str; +} + +} // namespace roctracer diff --git a/src/util/util.h b/src/util/util.h new file mode 100644 index 0000000000..5b286bcbb2 --- /dev/null +++ b/src/util/util.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2022 Advanced Micro Devices, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#pragma once + +#include +#include + +namespace roctracer { + +extern std::string string_vprintf(const char* format, va_list va); + +extern std::string string_printf(const char* format, ...) +#if defined(__GNUC__) + __attribute__((format(printf, 1, 2))) +#endif // defined (__GNUC__) + ; + +} // namespace roctracer \ No newline at end of file