diff --git a/.gitmodules b/.gitmodules index cb80a35a..bfdcdf53 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,7 @@ [submodule "third_party/demumble"] path = third_party/demumble url = https://github.com/nico/demumble.git +[submodule "third_party/rustc-demangle"] + path = third_party/rustc-demangle + url = https://github.com/zokier/rustc-demangle.git + branch = capi diff --git a/CMakeLists.txt b/CMakeLists.txt index 2490ebe2..46cea8eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ project (Bloaty) # Options we define for users. option(BLOATY_ENABLE_ASAN "Enable address sanitizer." OFF) option(BLOATY_ENABLE_UBSAN "Enable undefined behavior sanitizer." OFF) +option(BLOATY_ENABLE_RUSTC_DEMANGLE "Use rustc-demangle to demangle Rust symbols" OFF) # Set default build type. if(NOT CMAKE_BUILD_TYPE) @@ -36,6 +37,9 @@ include_directories(third_party/protobuf/src) include_directories(.) include_directories(src) include_directories(third_party/abseil-cpp) +if(BLOATY_ENABLE_RUSTC_DEMANGLE) + include_directories(third_party/rustc-demangle/rustc-demangle-capi/include) +endif() include_directories("${CMAKE_CURRENT_BINARY_DIR}/src") # Baseline build flags. @@ -67,6 +71,21 @@ if(BLOATY_ENABLE_UBSAN) set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fsanitize=undefined") endif() +if(BLOATY_ENABLE_RUSTC_DEMANGLE) + set(BLOATY_RUSTC_DEMANGLE_LIB_FILE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/rustc-demangle/target/release/librustc_demangle.a) + add_definitions(-DBLOATY_ENABLE_RUSTC_DEMANGLE) + add_custom_command( + OUTPUT ${BLOATY_RUSTC_DEMANGLE_LIB_FILE} + COMMAND cargo build --manifest-path ${CMAKE_CURRENT_SOURCE_DIR}/third_party/rustc-demangle/Cargo.toml --all --release + ) + # add_custom_target(rustc_demangle_target DEPENDS ${BLOATY_RUSTC_DEMANGLE_LIB_FILE}) + add_library(rustc_demangle STATIC IMPORTED GLOBAL) + add_dependencies(rustc_demangle ${BLOATY_RUSTC_DEMANGLE_LIB_FILE}) + set_target_properties(rustc_demangle PROPERTIES + IMPORTED_LOCATION ${BLOATY_RUSTC_DEMANGLE_LIB_FILE} + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/third_party/rustc-demangle/rustc-demangle-capi/include) +endif() + if(DEFINED ENV{CXXFLAGS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{CXXFLAGS}") endif() @@ -106,7 +125,9 @@ add_library(libbloaty ) set(LIBBLOATY_LIBS libbloaty libprotoc re2 capstone-static) - +if(BLOATY_ENABLE_RUSTC_DEMANGLE) + set(LIBBLOATY_LIBS "${LIBBLOATY_LIBS}" rustc_demangle dl) +endif() if(DEFINED ENV{LIB_FUZZING_ENGINE}) message("LIB_FUZZING_ENGINE set, building fuzz_target instead of Bloaty") diff --git a/src/bloaty.cc b/src/bloaty.cc index 71af7e88..79924ce1 100644 --- a/src/bloaty.cc +++ b/src/bloaty.cc @@ -69,6 +69,15 @@ static void Throw(const char *str, int line) { #define THROW(msg) Throw(msg, __LINE__) #define THROWF(...) Throw(absl::Substitute(__VA_ARGS__).c_str(), __LINE__) +#ifdef BLOATY_ENABLE_RUSTC_DEMANGLE +#include "rustc_demangle.h" +#else +int rustc_demangle(const char *mangled, char *out, size_t out_size) { + THROW("rustc-demangle not enabled"); + return 0; +} +#endif + namespace bloaty { // Use a global since we would have to plumb it through so many call-stacks @@ -98,6 +107,7 @@ constexpr DataSourceDefinition data_sources[] = { "symbols from symbol table (configure demangling with --demangle)"}, {DataSource::kRawSymbols, "rawsymbols", "unmangled symbols"}, {DataSource::kFullSymbols, "fullsymbols", "full demangled symbols"}, + {DataSource::kRustSymbols, "rustsymbols", "rust demangled symbols"}, {DataSource::kShortSymbols, "shortsymbols", "short demangled symbols"}, }; @@ -249,6 +259,13 @@ std::string ItaniumDemangle(string_view symbol, DataSource source) { } else { return std::string(symbol); } + } else if (source == DataSource::kRustSymbols) { + char demangled[1024]; + if (::rustc_demangle(demangle_from.data(), demangled, sizeof(demangled))) { + return std::string(demangled); + } else { + return std::string(symbol); + } } else if (source == DataSource::kFullSymbols) { char* demangled = __cxa_demangle(demangle_from.data(), NULL, NULL, NULL); @@ -1203,6 +1220,8 @@ class Bloaty { return DataSource::kRawSymbols; case Options::DEMANGLE_SHORT: return DataSource::kShortSymbols; + case Options::DEMANGLE_RUST: + return DataSource::kRustSymbols; case Options::DEMANGLE_FULL: return DataSource::kFullSymbols; default: @@ -1783,6 +1802,8 @@ bool DoParseOptions(bool skip_unknown, int* argc, char** argv[], options->set_demangle(Options::DEMANGLE_SHORT); } else if (option == "full") { options->set_demangle(Options::DEMANGLE_FULL); + } else if (option == "rust") { + options->set_demangle(Options::DEMANGLE_RUST); } else { THROWF("unknown value for --demangle: $0", option); } diff --git a/src/bloaty.h b/src/bloaty.h index 1a39e5f6..454f0da5 100644 --- a/src/bloaty.h +++ b/src/bloaty.h @@ -77,6 +77,7 @@ enum class DataSource { kRawSymbols, kFullSymbols, + kRustSymbols, kShortSymbols }; diff --git a/src/bloaty.proto b/src/bloaty.proto index 5f2a1bf8..355f35b6 100644 --- a/src/bloaty.proto +++ b/src/bloaty.proto @@ -44,6 +44,7 @@ message Options { DEMANGLE_SHORT = 0; DEMANGLE_FULL = 1; DEMANGLE_NONE = 2; + DEMANGLE_RUST = 3; } optional Demangle demangle = 5 [default = DEMANGLE_SHORT]; diff --git a/src/elf.cc b/src/elf.cc index 9401847a..030796ef 100644 --- a/src/elf.cc +++ b/src/elf.cc @@ -1254,6 +1254,7 @@ class ElfObjectFile : public ObjectFile { case DataSource::kRawSymbols: case DataSource::kShortSymbols: case DataSource::kFullSymbols: + case DataSource::kRustSymbols: ReadELFSymbols(debug_file().file_data(), sink, nullptr, false); break; case DataSource::kArchiveMembers: diff --git a/third_party/rustc-demangle b/third_party/rustc-demangle new file mode 160000 index 00000000..2495462a --- /dev/null +++ b/third_party/rustc-demangle @@ -0,0 +1 @@ +Subproject commit 2495462acc0c5c45d378778555769998e7c998e1